Skip to main content
Back to blog// general

NestJS Unit & Integration Tests

Testing is a crucial part of software development, ensuring that your code works as expected and preventing bugs from making their way into production. In this blog post, we will explore how to write

NK

Nicanor Korir

Author

July 22, 2024
14 min read
nestjstdd (test-driven development)unit testingintegration testinge2etesting

Testing is a crucial part of software development, ensuring that your code works as expected and preventing bugs from making their way into production. In this blog post, we will explore how to write unit and integration tests for a NestJS application, covering everything from the basics to more advanced techniques.

Checkout parts 1 & 2 of the NestJS series

Pros and Cons of Writing Tests

Pros

  1. Improved Code Quality:

* Writing tests ensures that your code works as expected and helps catch bugs early in the development process.

  1. Refactoring Confidence:

* Tests provide a safety net that allows you to refactor your code with confidence, knowing that any breaking changes will be caught by your tests.

  1. Documentation:

* Tests serve as documentation for your code, showing how different parts of your application are expected to behave.

  1. Reduced Bugs in Production:

* By catching issues early, tests reduce the likelihood of bugs making it into production, leading to more reliable software.

  1. Encourages Best Practices:

* Writing tests encourages best practices in software development, such as modularity and separation of concerns.

Cons

  1. Time-Consuming:

* Writing tests can be time-consuming, especially for large applications with many components.

  1. Maintenance Overhead:

* Tests need to be maintained along with the code. Changes in the application may require updates to the tests.

  1. Initial Learning Curve:

* There is an initial learning curve associated with writing effective tests, particularly for beginners.

Types of Tests

  • Unit Testing: Tests individual components or functions for correctness.
  • Integration Testing: Ensures that different components or systems work together as expected.
  • System Testing: Tests the complete and integrated software system to evaluate its compliance with the specified requirements.
  • End-to-End (E2E) Testing: Simulates real user scenarios to validate the entire application workflow.
  • Acceptance Testing: Validates that the software meets business requirements and is ready for deployment.
  • Performance Testing: Assesses the speed, responsiveness, and stability of the software under various conditions.
  • Security Testing: Identifies vulnerabilities and ensures the software is secure against attacks.

Prerequisites

Before we dive into testing, make sure you have the following set up:

  • Node.js and npm installed
  • A basic understanding of JavaScript/TypeScript
  • A NestJS application (You can create one using the NestJS CLI or go to NestJS 101)

Setting Up the NestJS Application

If you don't already have a NestJS application, you can create one using the NestJS CLI or go to NestJS 101 to get started with a simple API:

YAML
yaml
1
2
3

Introduction to Testing in NestJS

NestJS uses Jest as the default testing framework. Jest is a powerful and flexible testing framework that provides a great developer experience with features like zero configuration, snapshot testing, and built-in mocking.

Alternatives of Jest you can configure:

  • Mocha - Highly configurable, supports various assertion libraries
  • Jasmine - Behavior-driven, simple, built-in assertions
  • Ava - Concurrent test running, minimalistic, async/await support

Testing Files Structure

By default, NestJS places test files alongside the source files with an .spec.ts extension. This helps in keeping the tests close to the code they are testing.

Writing Unit Tests

Unit tests focus on testing individual units of code, such as functions or classes, in isolation from other parts of the application.

Example: Testing a Service

Let's start by writing a unit test for a simple service. Consider the following cats.service.ts:

TypeScript
typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

To test this service, create a cats.service.spec.ts file:

TypeScript
typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

Running the Tests

You can run the tests using the following command:

Bash
bash

Writing Integration Tests

Integration tests focus on testing the interactions between different parts of the application. In NestJS, this often involves testing the controllers and their interactions with services.

Example: Testing a Controller

Consider the following cats.controller.ts:

TypeScript
typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

To test this controller, create a cats.controller.spec.ts file:

TypeScript
typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

Advanced Testing Techniques

Mocking Dependencies

In real-world applications, services often depend on other services or databases. To isolate the unit being tested, we can mock these dependencies.

Consider the following cats.service.ts with a dependency on CatsRepository:

TypeScript
typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

To test this service, create a cats.service.spec.ts file:

TypeScript
typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

E2E Testing

End-to-end (E2E) tests verify the complete flow of the application, from the user interface to the backend services. NestJS supports E2E testing with Jest.

Setting Up E2E Tests

NestJS provides a sample E2E test in the test folder. You can modify it to suit your needs.

TypeScript
typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

Running E2E Tests

You can run E2E tests using the following command:

YAML
yaml

Considerations When Writing NestJS Tests

  1. Isolation: Ensure that unit tests isolate the component being tested. Mock dependencies to avoid testing multiple units at once.
  1. Coverage: Aim for high test coverage but focus on testing critical parts of your application first.
  1. Readability: Write tests that are easy to read and understand. Use descriptive test names and clear assertions.
  1. Maintainability: Keep tests maintainable by refactoring them alongside your code. Avoid brittle tests that break with minor changes in the code.
  1. Speed: Keep unit tests fast by avoiding external dependencies like databases or network calls. Integration and E2E tests can be slower but should still be optimized for performance.

Testing is an essential part of software development, ensuring that your code is reliable and maintainable. By following these practices and continuously writing tests, you can build robust NestJS applications that stand the test of time.

Stay tuned for more tutorials and deep dives into the world of NestJS!

Stay in the Loop

Get occasional updates on AI engineering, robotics projects, and lessons from building startups. No spam, unsubscribe anytime.