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 readyPremium
A concise answer to help you respond confidently on this topic during an interview.