Nest.js 框架测试

class 测试

测试是确保软件质量和可维护性的关键组成部分。在 Nest.js 中,我们可以使用 Jest 作为默认的测试框架来进行单元测试和集成测试。本文将详细介绍如何在 Nest.js 中进行测试,包括基本配置、单元测试、集成测试的编写及示例。

1. Jest 概述

Jest 是一个功能强大且易于使用的 JavaScript 测试框架,提供了丰富的功能,包括:

  • 简单的 API
  • 快速的测试执行
  • 断言库
  • 模拟功能
  • 代码覆盖率报告

2. 环境配置

Nest.js 项目默认使用 Jest 进行测试,因此你可以直接使用它。如果你的项目还没有 Jest,可以通过以下命令安装:

npm install --save-dev jest @nestjs/testing ts-jest @types/jest

3. 单元测试

单元测试的目的是验证单个组件的功能,确保其在不同输入下的行为符合预期。

3.1 示例:用户服务单元测试

假设我们有一个简单的用户服务:

3.1.1 创建用户服务

users.service.ts 中:

import { Injectable } from '@nestjs/common';

@Injectable()
export class UsersService {
  private users = [];

  create(user: { name: string; email: string }) {
    this.users.push(user);
    return user;
  }

  findAll() {
    return this.users;
  }
}

3.1.2 创建单元测试

users.service.spec.ts 中:

import { Test, TestingModule } from '@nestjs/testing';
import { UsersService } from './users.service';

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

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

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

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

  it('should create a user', () => {
    const user = { name: 'John Doe', email: 'john@example.com' };
    expect(service.create(user)).toEqual(user);
  });

  it('should find all users', () => {
    const user1 = { name: 'John Doe', email: 'john@example.com' };
    const user2 = { name: 'Jane Doe', email: 'jane@example.com' };
    service.create(user1);
    service.create(user2);
    expect(service.findAll()).toEqual([user1, user2]);
  });
});

3.2 运行单元测试

运行以下命令执行测试:

npm run test

你应该会看到所有测试通过的输出。

4. 集成测试

集成测试的目的是验证多个组件的协作是否正常。

4.1 示例:用户控制器集成测试

假设我们有一个用户控制器来处理 HTTP 请求:

4.1.1 创建用户控制器

users.controller.ts 中:

import { Controller, Post, Body, Get } from '@nestjs/common';
import { UsersService } from './users.service';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Post()
  create(@Body() createUserDto: { name: string; email: string }) {
    return this.usersService.create(createUserDto);
  }

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

4.1.2 创建集成测试

users.controller.spec.ts 中:

import { Test, TestingModule } from '@nestjs/testing';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';

describe('UsersController', () => {
  let controller: UsersController;
  let service: UsersService;

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

    controller = module.get<UsersController>(UsersController);
    service = module.get<UsersService>(UsersService);
  });

  it('should create a user', () => {
    const user = { name: 'John Doe', email: 'john@example.com' };
    jest.spyOn(service, 'create').mockImplementation(() => user);

    expect(controller.create(user)).toEqual(user);
  });

  it('should find all users', () => {
    const user1 = { name: 'John Doe', email: 'john@example.com' };
    const user2 = { name: 'Jane Doe', email: 'jane@example.com' };
    jest.spyOn(service, 'findAll').mockImplementation(() => [user1, user2]);

    expect(controller.findAll()).toEqual([user1, user2]);
  });
});

5. 模拟服务

在测试中,我们可以使用 Jest 的 jest.spyOn() 方法来模拟服务的方法。这在集成测试中尤其有用,以确保我们可以控制依赖的行为。

6. 使用 Supertest 进行端到端测试

对于 HTTP 请求的测试,我们可以使用 Supertest 来模拟 HTTP 请求。

6.1 安装 Supertest

npm install --save-dev supertest

6.2 示例:端到端测试

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('Users (e2e)', () => {
  let app: INestApplication;

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

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

  it('/users (POST)', () => {
    return request(app.getHttpServer())
      .post('/users')
      .send({ name: 'John Doe', email: 'john@example.com' })
      .expect(201)
      .expect(({ body }) => {
        expect(body).toEqual({
          name: 'John Doe',
          email: 'john@example.com',
        });
      });
  });

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

7. 代码覆盖率

在运行测试时,Jest 也支持生成代码覆盖率报告。可以通过以下命令生成覆盖率报告:

npm run test -- --coverage

8. 总结

在本文中,我们详细介绍了如何在 Nest.js 中使用 Jest 进行单元测试和集成测试。我们涵盖了以下内容:

  • 单元测试:验证单个组件的功能。
  • 集成测试:验证多个组件之间的协作。
  • 模拟服务:使用 Jest 模拟服务的方法。
  • 端到端测试:使用 Supertest 模拟 HTTP 请求。

通过实施测试,我们可以确保代码的质量和稳定性,使维护和扩展变得更加简单和安全。Nest.js 提供的测试支持使得测试变得简单而直观,为开发者提供了强大的工具来构建高质量的应用程序。

评论区
评论列表
menu