Nest.js: How to Write Unit Tests with Jest

Updated: January 1, 2024 By: Guest Contributor Post a comment

Overview

Testing is a crucial component in the development process, ensuring code reliability and stability. This tutorial will guide you through the essentials of writing unit tests in Nest.js using Jest. From setting up your testing environment to advanced testing patterns, learn to elevate the quality of your Nest.js applications.

Setting Up Jest in Nest.js

To begin writing unit tests in Next.js applications, you first need to install Jest and the necessary testing utilities. Assuming you have a Nest.js project created, let’s install Jest:

npm install --save-dev jest @nestjs/testing ts-jest

Next, you need to configure Jest by creating a jest.config.js file in your project root:

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
};

Writing Your First Unit Test

We’ll start by writing a simple unit test for a service method. Create a new file in your service directory named <service>.spec.ts. Here’s how a basic test looks:

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

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

    service = module.get<CatsService>(CatsService);
  });

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

  // Additional tests here
});

Mocking Dependencies

For isolating the service under test, you may need to mock its dependencies. Here’s an example of mocking a repository within a service test:

describe('CatsService with mock repository', () => {
  let service: CatsService;
  let mockRepository: MockType<Repository<Cat>>;

  beforeEach(async () => {
    mockRepository = createMockRepository();

    const module = await Test.createTestingModule({
      providers: [
        CatsService,
        {
          provide: getRepositoryToken(Cat),
          useValue: mockRepository,
        },
      ],
    }).compile();

    service = module.get<CatsService>(CatsService);
  });

  // Tests using the mockRepository
});

Advanced Unit Testing Patterns

As your tests become more complex, you might require more intricate setups. This can include using factories, spies, and interceptors. Let’s look at using Jest spies for observing function calls:

describe('CatsService with spies', () => {
  let service: CatsService;
  let saveSpy: jest.SpyInstance;

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

    service = module.get<CatsService>(CatsService);
    saveSpy = jest.spyOn(service, 'saveCat');
  });

  it('should call saveCat', async () => {
    const catDto = { name: 'Test', breed: 'Test Breed' };
    await service.create(catDto);
    expect(saveSpy).toHaveBeenCalledWith(catDto);
  });
});

As you progress, leverage test coverage analysis to identify untested parts of your codebase, ultimately striving for thorough test coverage.

Conclusion

Unit testing with Jest in Nest.js enhances the robustness of your application and gives you confidence in its functionality. By systematically building up your test suite and integrating mock objects and spies, you can simulate various scenarios and catch potential issues early in the development cycle. Remember, quality tests are as vital as quality code.