Sling Academy
Home/Node.js/How to Write Unit Tests in NestJS with Jest and Supertest

How to Write Unit Tests in NestJS with Jest and Supertest

Last updated: December 31, 2023

Introduction

Testing is a critical step in the software development process. In this tutorial, we leverage Jest and Supertest to create reliable unit tests for applications built with NestJS, a Node.js framework. Learn how to ensure your NestJS services and controllers behave as expected under various conditions.

Setting Up the Environment

To start writing unit tests in NestJS, you must first set up your environment:

// Install Jest and the testing tools
$ npm install --save-dev @nestjs/testing jest @types/jest ts-jest
$ npm install --save-dev supertest @types/supertest

// Add a jest.config.js file
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
};

// Add the following scripts to your package.json
"scripts": {
  "test": "jest",
  "test:watch": "jest --watch",
  "test:cov": "jest --coverage",
}

With Jest and Supertest installed, and the configuration in place, you’re ready to begin unit testing your NestJS application.

Testing NestJS Services

Begin with testing your services:

import { Test, TestingModule } from '@nestjs/testing';
import { MyService } from './my.service';

describe('MyService', () => {
  let service: MyService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [MyService],
    }).compile();

    service = module.get(MyService);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });

  // Add more tests here
});

This is a simple test to check that the service is properly instantiated.

Testing Controllers with Supertest

Moving forward, combine efforts with Supertest to test controllers:

import { INestApplication } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import * as request from 'supertest';
import { AppModule } from './../src/app.module';

describe('AppController (e2e)', () => {
  let app: INestApplication;

  beforeEach(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    await app.init();
  });

  it('/ (GET)', () => {
    return request(app.getHttpServer())
      .get('/')
      .expect(200)
      .expect('Hello World!');
  });

  afterEach(async () => {
    await app.close();
  });
});

Here we’re using Supertest to perform end-to-end tests on the application’s endpoint.

Mocking Dependencies

Mocking is essential for isolating tests. NestJS provides tools for easy mocking:

import { MyService } from './my.service';

describe('MyService', () => {
  let service: MyService;
  let mockRepository: MockRepository;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        MyService,
        {
          provide: MyRepository,
          useClass: MockRepository
        }
      ],
    }).compile();

    service = module.get(MyService);
    mockRepository = module.get(MyRepository);
  });

  // Tests using the mocked repository here
});

Create realistic and controlled conditions by using mocked versions of your dependencies.

You can further enhance your unit tests by simulating more complex scenarios. NestJS’s powerful testing utilities enable developers to craft thorough test suites that cover all logic branches.

Creating Test Suites

While individual tests are useful, grouping similar tests into suites provides better organization and readability:

// Individual test suites with their own beforeEach, afterEach, and collection of `it` blocks for a comprehensive testing strategy

Use Jest’s powerful test suite capabilities to ensure every aspect of your NestJS application is verified.

Handling Asynchronous Code

In a Node.js environment, dealing with asynchronous operations is the norm. Here’s how you can test asynchronous service methods in NestJS:

it('should do async operation', async () => {
  await expect(service.someAsyncMethod()).resolves.toEqual(expectedOutcome);
});

Ensure your async functions behave as intended by properly resolving promises and managing exceptions.

Applying TDD

Test-Driven Development (TDD) is an approach where you write tests first, before coding the actual feature. Applying TDD with NestJS and Jest can significantly improve the quality and maintainability of your code.

Conclusion

Unit testing is a vital part of NestJS application development, ensuring your codebase is robust and functionally correct. With Jest and Supertest, NestJS apps can benefit from efficient, expressive, and powerful testing suites. By following this tutorial, you’re well on your way to mastering unit tests in your NestJS applications.

Next Article: How to Use Multiple Databases in NestJS

Previous Article: How to integrate Paypal payment in NestJS

Series: Nest.js Tutorials: From Basics to Advanced

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates