1

I have a REST API and a SPA application, with Auth0 server issuing access tokens and enabling end users to login with their social identity provider. The API expects to receive a JWT access token with the user's external identity in the sub claim with each request. After the user registers for the first time (and provides some additional details), a local user record is stored in the application database together with their external identity. For each subsequent request, the appropriate domain User is reconstructed from the database on the basis of the external identity received in the token and the rest of the business logic ensues.

What would be the appropriate way to test API endpoints? Auth0 provides a token for M2M use, but that token isn't tied to any of the local user records in the application database. Mocking the service that reconstructs the domain User using the received external identity to return the user intended as the invoker of the action being tested seems cumbersome. Moreover, if the controllers are very thin and use the service layer directly for invoking business logic, what would be the downside of not testing them at all and only testing the service layer beneath?

1 Answer 1

0

The question you should ask yourself is, what exactly do you want to test?

Most but very basic systems have multiple types of tests, and each of the types has its own purpose.

For instance, if your API contains some complex logic, you would need to have a bunch of unit tests which test specifically this logic, in isolation. Those tests run in their own context, and they call parts of your code directly. In other words, they don't need the API to run, and they don't even need to know that you're writing an API.

Given that unit tests run in isolation, they won't help you to catch regressions at the level of the interface between, say, two classes. Therefore, you'll add integration tests. Same here, those tests won't bother knowing whether you're writing an API or a desktop application or an embedded system.

Now, both unit tests and integration tests won't catch the regressions in the way the API is actually used. Say at some point, a given call relied on the presence of the Hello-World HTTP header, and later on, you decided to prefix the header by X-. How would you know that the clients are still working?

Well, in order to mitigate the risk of breaking the clients, you do a system test which uses the actual client library which calls your actual API. Those tests will be slow (compared to sub-millisecond unit tests), so you'll have less of those tests—say a few thousands unit tests, a few hundreds of integration tests, and a few dozens of system tests. But they'll catch anyway the bugs that the other two types won't catch.

Should you use authentication in those system tests? It depends. If it's simple and fast, do it. If it's slow, don't. If you don't, there are several approaches to “bypass” authentication. You can run your API in special mode, with fake authentication based on, for instance, cookies, or HTTP headers in the request, where the user ID is sent in plain text, and no password or secret is needed.

Make sure you still have a smoke test. This is a test that runs your entire system in a production-like context. Its goal is to find that the system actually starts, and that it is not completely broken. In general, a smoke test runs a given scenario representing an important part of the application. For instance, for an e-commerce website, a smoke test could consist of registering on the website, searching for a product, adding it to cart, buying it, and then cancelling the purchase before the product is shipped.

1
  • Thank you for this elaborate overview of different types of tests and the motivation behind them. When I thought about testing my API, my mind immediately jumped to integration testing - I didn't even consider testing the controllers as units, in isolation. I will consider bypassing the authentication in some way based on your suggestions.
    – 0lt
    Feb 11, 2022 at 9:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.