Projects created with nest new come with Jest, Supertest and Nest's testing package, @nestjs/testing, already configured. This chapter covers unit tests for services and controllers, end-to-end tests that boot the whole application, and testing a plain Express app with Supertest.
Running tests
Unit tests are the *.spec.ts files inside src; end-to-end tests are the *.e2e-spec.ts files in test, which use their own Jest config, test/jest-e2e.json.
npm run test # unit tests
npm run test:watch # re-run on file changes
npm run test:cov # coverage report
npm run test:e2e # end-to-end tests
Unit testing a service
A service without dependencies can be tested like any class, by calling new. When it has dependencies, build a testing module with Test.createTestingModule and replace real providers with fakes.
// src/users/users.service.spec.ts
import { Test } from "@nestjs/testing";
import { getRepositoryToken } from "@nestjs/typeorm";
import { User } from "./entities/user.entity";
import { UsersService } from "./users.service";
describe("UsersService", () => {
let service: UsersService;
const repository = { find: jest.fn(), create: jest.fn(), save: jest.fn() };
beforeEach(async () => {
const moduleRef = await Test.createTestingModule({
providers: [UsersService, { provide: getRepositoryToken(User), useValue: repository }],
}).compile();
service = moduleRef.get(UsersService);
});
it("returns every user", async () => {
repository.find.mockResolvedValue([{ id: 1, name: "Kim" }]);
await expect(service.findAll()).resolves.toHaveLength(1);
});
});
getRepositoryToken(User) is the injection token that @InjectRepository(User) looks up, so the service logic runs without a database.
Unit testing a controller
For controllers, fake the service. When you register the real provider and want to swap it, use overrideProvider.
// src/users/users.controller.spec.ts
import { Test } from "@nestjs/testing";
import { UsersController } from "./users.controller";
import { UsersService } from "./users.service";
describe("UsersController", () => {
it("delegates to the service", async () => {
const usersService = { findAll: jest.fn().mockResolvedValue([]) };
const moduleRef = await Test.createTestingModule({
controllers: [UsersController],
providers: [UsersService],
})
.overrideProvider(UsersService)
.useValue(usersService)
.compile();
const controller = moduleRef.get(UsersController);
await controller.findAll();
expect(usersService.findAll).toHaveBeenCalled();
});
});
End-to-end tests with Supertest
An e2e test builds the app from real modules and sends HTTP requests with Supertest. Apply the same global setup as main.ts, such as pipes, to the test app.
// test/users.e2e-spec.ts
import { INestApplication, ValidationPipe } from "@nestjs/common";
import { Test } from "@nestjs/testing";
import request from "supertest";
import { AppModule } from "../src/app.module";
describe("Users (e2e)", () => {
let app: INestApplication;
beforeAll(async () => {
const moduleRef = await Test.createTestingModule({ imports: [AppModule] }).compile();
app = moduleRef.createNestApplication();
app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
await app.init();
});
afterAll(async () => {
await app.close();
});
it("rejects an invalid body", () => {
return request(app.getHttpServer()).post("/users").send({ name: "" }).expect(400);
});
});
app.getHttpServer() returns the underlying HTTP server, so no port is needed. For e2e tests that touch a database, use a dedicated test database or start a throwaway container per run with a tool such as Testcontainers, keeping production data out of reach.
Testing an Express app
Express works the same way. If app.js only exports the app, as in the project structure chapter, Supertest can call it directly.
npm i -D jest supertest
// test/users.test.js
const request = require("supertest");
const app = require("../src/app");
test("GET /users/1 returns the user", async () => {
const response = await request(app).get("/users/1").expect(200);
expect(response.body.id).toBe("1");
});
Node's built-in test runner, node:test, also pairs well with Supertest.
Summary
- Nest projects come with Jest for unit tests and Supertest for end-to-end tests.
- Build test modules with
Test.createTestingModule and replace dependencies with useValue or overrideProvider. - E2E tests use
createNestApplication() and app.getHttpServer() to exercise the real request pipeline, with the same global setup as production. - Splitting
app from listen makes Express apps easy to test with Supertest.
0 commentaire
Se connecter · Connectez-vous pour laisser un commentaire.