Publicado · en mejora
Guía de NestJS · Express · 5/6
Por ahora, este capítulo solo está disponible en inglés.
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.
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 testsA 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.
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();
});
});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.
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.
Test.createTestingModule and replace dependencies with useValue or overrideProvider.createNestApplication() and app.getHttpServer() to exercise the real request pipeline, with the same global setup as production.app from listen makes Express apps easy to test with Supertest.
0 comentarios
Iniciar sesión · Inicia sesión para dejar un comentario.
Sé el primero en comentar.