Dev Conventions
  • Dev Conventions
  • Git
    • Branch Flow
    • Conventional Commits
    • Pull requests template
    • Before making the PRs in typescript, keep in mind
  • Typescript
    • Introduction
    • Good practices
    • Solid
    • Using pnpm for Package Management
    • NestJs
    • NextJs
    • React
    • NestJs Testing
    • React Testing
    • Npm Registry
  • PYTHON
    • Introduction
    • Good practices
    • Testing
    • Naming Convention
  • DevOps
    • Introduction
    • Github Actions
    • Creating a Github Actions Workflow
  • Agile
    • Story Points
Powered by GitBook
On this page
  • Testing with NestJS and Jest
  • Setting Up Testing Environment
  • Writing Tests
  • Running Tests
  • Conclusion
  1. Typescript

NestJs Testing

Testing with NestJS and Jest

NestJS is a progressive Node.js framework for building efficient, reliable, and scalable server-side applications. It uses modern JavaScript, built with and fully supporting TypeScript. Jest is a delightful JavaScript Testing Framework with a focus on simplicity. It works with projects using Babel, TypeScript, Node.js, React, Angular, Vue.js, and more.

This documentation will guide you through the process of setting up and writing tests for your NestJS application using Jest.

Setting Up Testing Environment

Install Jest and Related Packages

NestJS comes with Jest pre-configured, but you need to install the necessary packages:

pnpm add--save-dev jest @types/jest ts-jest @nestjs/testing

Configure Jest

Create a jest.config.js file in the root of your project with the following content:

module.exports = {
  moduleFileExtensions: ['js', 'json', 'ts'],
  rootDir: 'src',
  testRegex: '.*\\.spec\\.ts$',
  transform: {
    '^.+\\.(t|j)s$': 'ts-jest',
  },
  collectCoverageFrom: [
    '**/*.(t|j)s'
  ],
  coverageDirectory: '../coverage',
  testEnvironment: 'node',
};

Writing Tests

Unit Testing

Unit tests focus on testing individual components or services. They ensure that each part of your application behaves as expected in isolation.

Example Service Test

Consider a simple CatsService:

// cats.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class CatsService {
  private readonly cats = [];

  findAll(): any[] {
    return this.cats;
  }

  create(cat: any) {
    this.cats.push(cat);
  }
}

Create a test file named cats.service.spec.ts:

// cats.service.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { CatsService } from './cats.service';

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

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

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

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

  it('should return an array', () => {
    expect(service.findAll()).toBeInstanceOf(Array);
  });

  it('should create a cat', () => {
    const cat = { name: 'Tom' };
    service.create(cat);
    expect(service.findAll()).toContain(cat);
  });
});

Integration Testing

Integration tests ensure that different parts of the application work together as expected.

Example Controller Test

Consider a CatsController that uses the CatsService:

// cats.controller.ts
import { Controller, Get, Post, Body } from '@nestjs/common';
import { CatsService } from './cats.service';

@Controller('cats')
export class CatsController {
  constructor(private readonly catsService: CatsService) {}

  @Get()
  findAll() {
    return this.catsService.findAll();
  }

  @Post()
  create(@Body() cat: any) {
    this.catsService.create(cat);
  }
}

Create a test file named cats.controller.spec.ts:

// cats.controller.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

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

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

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

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

  it('should return an array', () => {
    const result = [];
    jest.spyOn(service, 'findAll').mockImplementation(() => result);
    expect(controller.findAll()).toBe(result);
  });

  it('should create a cat', () => {
    const cat = { name: 'Tom' };
    const createSpy = jest.spyOn(service, 'create');
    controller.create(cat);
    expect(createSpy).toHaveBeenCalledWith(cat);
  });
});

E2E Testing

End-to-end (E2E) tests check the entire flow of your application, ensuring that all parts work together correctly.

Example E2E Test

NestJS provides a separate project structure for E2E tests. Create a test file named app.e2e-spec.ts in the test directory:

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

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

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

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

  it('/cats (GET)', () => {
    return request(app.getHttpServer())
      .get('/cats')
      .expect(200)
      .expect([]);
  });

  it('/cats (POST)', () => {
    const cat = { name: 'Tom' };
    return request(app.getHttpServer())
      .post('/cats')
      .send(cat)
      .expect(201)
      .expect((res) => {
        expect(res.body.name).toEqual(cat.name);
      });
  });

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

Running Tests

To run your tests, use the following command:

pnpm run test

For E2E tests, use:

pnpm run test:e2e

Conclusion

By setting up Jest with NestJS, you can write comprehensive tests that ensure the correctness of your application at different levels. Unit tests validate individual components, integration tests check the interaction between components, and E2E tests verify the application's behavior as a whole. Following these practices will help you maintain a robust and reliable codebase.

PreviousReactNextReact Testing

Last updated 11 months ago