Skip to main content
Practice Problems

How to test a NestJS application?

Testing NestJS Applications

NestJS uses Jest by default and provides the @nestjs/testing package to create isolated test modules. The framework supports both unit tests (isolated service/controller tests) and end-to-end (e2e) tests (full HTTP stack).


Unit Testing a Service

typescript
// users/users.service.spec.ts import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { UsersService } from './users.service'; import { User } from './entities/user.entity'; import { NotFoundException } from '@nestjs/common'; describe('UsersService', () => { let service: UsersService; let repo: jest.Mocked<Repository<User>>; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ UsersService, { provide: getRepositoryToken(User), useValue: { find: jest.fn(), findOneBy: jest.fn(), create: jest.fn(), save: jest.fn(), delete: jest.fn(), }, }, ], }).compile(); service = module.get<UsersService>(UsersService); repo = module.get(getRepositoryToken(User)); }); describe('findOne()', () => { it('should return a user when found', async () => { const user: User = { id: 1, name: 'Alice', email: 'alice@test.com' } as User; repo.findOneBy.mockResolvedValue(user); const result = await service.findOne(1); expect(result).toEqual(user); expect(repo.findOneBy).toHaveBeenCalledWith({ id: 1 }); }); it('should throw NotFoundException when not found', async () => { repo.findOneBy.mockResolvedValue(null); await expect(service.findOne(99)).rejects.toThrow(NotFoundException); }); }); describe('create()', () => { it('should create and return a user', async () => { const dto = { name: 'Bob', email: 'bob@test.com' }; const user = { id: 2, ...dto } as User; repo.create.mockReturnValue(user); repo.save.mockResolvedValue(user); const result = await service.create(dto); expect(result).toEqual(user); }); }); });

Unit Testing a Controller

typescript
// users/users.controller.spec.ts describe('UsersController', () => { let controller: UsersController; let service: jest.Mocked<UsersService>; beforeEach(async () => { const module = await Test.createTestingModule({ controllers: [UsersController], providers: [ { provide: UsersService, useValue: { findAll: jest.fn().mockResolvedValue([]), findOne: jest.fn(), create: jest.fn(), }, }, ], }).compile(); controller = module.get<UsersController>(UsersController); service = module.get(UsersService); }); it('should return array from findAll()', async () => { const result = await controller.findAll(); expect(result).toEqual([]); expect(service.findAll).toHaveBeenCalled(); }); });

E2E Testing

typescript
// test/users.e2e-spec.ts import * as request from 'supertest'; describe('UsersController (e2e)', () => { let app: INestApplication; beforeAll(async () => { const moduleFixture = await Test.createTestingModule({ imports: [AppModule], }).compile(); app = moduleFixture.createNestApplication(); app.useGlobalPipes(new ValidationPipe({ whitelist: true })); await app.init(); }); afterAll(async () => await app.close()); it('GET /users → 200', () => { return request(app.getHttpServer()) .get('/users') .expect(200) .expect(res => { expect(Array.isArray(res.body)).toBe(true); }); }); it('POST /users → 201 with valid body', () => { return request(app.getHttpServer()) .post('/users') .send({ name: 'Alice', email: 'alice@test.com' }) .expect(201); }); it('POST /users → 400 with invalid body', () => { return request(app.getHttpServer()) .post('/users') .send({ name: 'A' }) // too short, no email .expect(400); }); });

Testing Guards

typescript
// Override guard in test const module = await Test.createTestingModule({ controllers: [UsersController], providers: [UsersService], }) .overrideGuard(JwtAuthGuard) .useValue({ canActivate: () => true }) // always allow .compile();

Summary

NestJS testing uses Test.createTestingModule() to build isolated module contexts. For unit tests, mock dependencies with jest.fn(). For e2e tests, create the full application with app.init() and use Supertest for HTTP requests. Override guards/pipes/interceptors using .overrideGuard(), .overridePipe(), etc.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems