API with NestJS #88. Testing a project with raw SQL using integration tests

JavaScript NestJS SQL

This entry is part 88 of 121 in the API with NestJS

Covering our project with tests can help us ensure that our application works as expected and is reliable. While unit tests play a significant role, they are not enough. Therefore, this article explains the significance of integration tests and implements them in a NestJS project that uses raw SQL queries.

The significance of integration tests

The role of a unit test is to cover an individual piece of code and verify if it works as expected. For example, a particular unit test suite can test a single function or a class.

When all our unit tests pass, it means that each part of our system works well on its own. However, that does not yet mean that all parts of the application interact with each other correctly. To verify the above, we need integration tests. Their job is to ensure that two or more pieces of our system integrate correctly.

Testing NestJS services

Writing integration tests does not mean we don’t mock any part of the application. For example, in our integration tests, we won’t be using an actual database.

Tests that verify the application from start to finish are referred to as end-to-end (E2E) tests. They should mimic a real system as close as possible.

posts.service.test.ts

The PostsService
when calling the create method with category ids
✓ should return an instance of the PostWithCategoryIdsModel

Above, we test if the class works well with the .

posts.service.ts

In our test, we only mock the . Thanks to that, we test if the integrates correctly with the .

posts.repository.ts

Mocking differently in each test

So far, in our test, we put all of our logic in a single function. An alternative for that is moving the setup code into the functions.

posts.service.test.ts

The PostsService
when calling the create method with category ids
✓ should return an instance of the PostWithCategoryIdsModel
✓ should return an object with the correct properties

Thanks to using , we can set up multiple tests using the same piece of code and avoid repeating it. We can take it further and change how we mock the at each test.

posts.service.test.ts

The PostsService
when calling the create method with category ids
✓ should return an instance of the PostWithCategoryIdsModel
✓ should return an object with the correct properties
when calling the create method without category ids
✓ should return an instance of the PostMode
✓ should return an object with the correct properties

Testing controllers

Another approach to integration tests is to include our controllers by performing HTTP requests. By doing that, we can more closely mimic how our application works in a real environment.

Since our application uses the , we need to add it explicitly.

The AuthenticationController
when making the /register POST request
and using an incorrect email
✓ should throw an error
and using the correct data
✓ should result with the 201 status
✓ should respond with the data without the password

The SuperTest library is quite powerful and allows us to verify the response differently. For example, we can ensure the response headers are correct. For a complete list of the features, check out the documentation.

Summary

In this article, we’ve gone through the idea of integration tests. We’ve described why they’re important and how they can benefit our application. We’ve also implemented integration tests with two different approaches. One of them required us to install the supertest library to simulate actual HTTP requests. All of the above allowed us to test our API more thoroughly and increase the confidence that we’re creating a reliable product.

Series Navigation<< API with NestJS #87. Writing unit tests in a project with raw SQLAPI with NestJS #89. Replacing Express with Fastify >>
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments