I have a restful api router , where it connects with database and returns some rows. So is it Unit test or Integration test ? From my knowledge, unit test doesn't connect with external services likes database, files, ... . and how to write an actual unit test for restful api ?
2 Answers
From my knowledge, unit test doesn't connect with external services likes database, files,
You're right. You're describing an integration test. It integrates all or some of the components in your system and tests them.
how to write an actual unit test for restful api ?
You don't really unit test the restful API because that's too big. Instead you unit test the units that make up the restful api. With most restful API, you write simple functions and then configure your framework to invoke the functions given a specific route. So unit test those functions.
For example in my REST API, authorization is a concern that is handled in the endpoint function. I have a function like so (pseudocode):
def insertBusiness(...)
if !auth.authenticated
return Unauthenticated
if !auth.getPermissions.contain(ADMIN)
return Unauthorized
else
bll.insertBusiness(...)
return Created
This function is configured in my REST framework to be executed when a POST
request is made to /businesses
for example.
It's useful write unit tests to cover this function. The bll
and auth
objects must be mocked--otherwise this would be an integration test. Here are some example test cases:
- When
auth.authenticated
returns false,insertBusiness
must returnUnauthenticated
- When
auth.getPermissions
does not containADMIN
,insertBusiness
must returnUnauthorized
- When
auth.authenticated
throws an exception,insertBusiness
must throw an exception - When
auth.getPermissions
throws an exception,insertBusiness
must throw an exception - When
auth.authenticated
returns null (if type is nullable or unchecked),insertBusiness
must throw an exception auth.getPermissions
returns null (if type is nullable or unchecked),insertBusiness
must throw an exception- When
bll.insertBusiness
throws an exception,insertBusiness
must throw an exception - When an authenicated user with
ADMIN
permissions,insertBusiness
must returnCreated
These tests are not implemented by making REST requests through the framework (again that would be an integration test). They're implemented by making calls directly on insertBusiness
For what it's worth, it's an integration test. The important difference is that it takes a bit longer to run, so it's not run multiple times a day during development but before acceptance into production.
The real question with a test is whether it gives useful information about the state of the system that the cost of running is worthwhile running it now. So better unit tests are fast and give feedback quickly, and integration tests tend to be run less often as they are slower, but if all your integration tests took less than a second to run you wouldn't lose anything running them on every build.
Usually we do a regression/integration test of our REST APIs using Python, mainly as that is what most of our users use to connect to the API to script our system. They are created using the unit test framework and run as part of the UAT process, or when we have made a change we suspect might cause an issue.
The tests of the REST API are run after the unit tests for the components the API operates upon are run (similar to those @Samuel describe). The purpose of testing the API is to make sure we don't break any scripts that the users of the API have written. Since the purpose of the API is to integrate between the external users' script and the rest of the system, you could mock the system, but since they are run less often as regression/integration tests we don't make that optimisation.