🦄 2024 独立开发者训练营,一起创业!查看介绍 / 立即报名(剩余8个优惠名额) →

Nest.js:测试(文档)

自动化测试是软件开发的基础,至少测试要覆盖到系统里的一些比较敏感的部分。我们需要使用不同类型的测试,比如集成测试、单元测试、e2e 测试等等,Nest 提供了一些工具可以改善创建这些测试的体验,默认集成了 Jest 测试框架,你也可以使用自己熟悉的测试框架。

安装

先得安装需要的包:

npm install @nestjs/testing --save-dev

单元测试

Unit testing,单元测试。Jest 是一个非常成熟的测试框架,框架可以用来运行测试,里面也提供了 assert 函数,测试替身,可以用来 mocking 或 spying 等等。

假设应用里有两个类:CatsController 与 CatsService。下面我们手工强制让调用 catsService.findAll() 方法的时候返回 result,这样我们就可以测试 catsController.findAll() 方法是否可以返回我们期望的结果了。

import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

describe('CatsController', () => {
  let catsController: CatsController;
  let catsService: CatsService;

  beforeEach(() => {
    catsService = new CatsService();
    catsController = new CatsController(catsService);
  });

  describe('findAll', () => {
    it('should return an array of cats', async () => {
      const result = ['test'];
      jest.spyOn(catsService, 'findAll').mockImplementation(() => result);

      expect(await catsController.findAll()).toBe(result);
    })
  });
});

上面这个测试并没有用到 Nest 测试工具,测试的类是手动实例化的,这种测试叫 isolated tests(独立测试)。

测试工具

在 @nestjs/testing 里提供的工具,重新创建上面这个测试。

import { Test } from '@nestjs/testing';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

describe('CatsController', () => {
  let catsController: CatsController;
  let catsService: CatsService;

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

    catsService = module.get(CatsService);
    catsController = module.get(CatsController);
  });

  describle('findAll', () => {
    it('should return an array of cats', async () => {
      const result = ['test'];
      jest.spyOn(catsService, 'findAll').mockImplementation(() => result);

      expect(await catsController.findAll()).toBe(result);
    })
  });
});

Test 类里有个 createTestingModule() 方法,接收的对象参数跟 @Module 一样。这个方法创建会一个 TestingModule 实例,里面有几个方法,在做单元测试时只有一个方法有用,就是 compile() ,模块被编译之后,可以使用 get() 方法获取到任意实例。要 mock 真正的实例,可以使用自定义 provider 覆盖已有 provider。

End-to-end 测试

我们的应用会越来越复杂,手工测试应用里提供的所有接口也会越来越困难,可以用 e2e 测试帮我们去测试。

import * as request from 'supertest';
import { Test } from '@nestjs/testing';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
import { INestApplication } from '@nestjs/common';

describle('Cats', () => {
  let app: INestApplication;
  let catsService = {
    findAll: () => ['test']
  };

  beforeAll(async () => {
    const module = await Test.createTestingModule({
      imports: [CatsModule],
    })
      .overrideProvider(CatsService)
      .useValue(catsService)
      .compile();

    app = module.createTestingModule();
    await app.init();
  });

  it('/GET cats', () => {
    return request(app.getHttpServer())
      .get('/cats')
      .expect(200)
      .expect({
        data: catsService.findAll(),
      });
  });

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

e2e 测试可以放在 e2e 目录里面,测试文件要有 .e2e-spec 或 .e2e-test 后缀。

cats.e2e-spec.ts 文件包含一个 HTTP 接口测试(/cats)。我们要用 app.getHttpServer() 方法获取到在后台运行的 Nest 应用的 HTTP 服务器。

TestingModule 实例提供了 overrideProvider() 方法,可以覆盖已有 provider ,还可以使用 overrideGuard(),overrideInterceptor(),overrideFilter() 还有 overridePipe 覆盖相应的东西。

编译的模块有下面几个方法:

  • createNestApplication(),基于模块创建 Nest 实例(返回 INestApplication)。需要使用 init() 方法手工初始化应用。
  • createNestMicroservice(),基于模块创建 Nest 微服务实例(返回 INestMicroservice)。
  • get(),获取控制器、provider 实例。
  • select(),从选择的模块里提取特定的实例。
微信好友

用微信扫描二维码,
加我好友。

微信公众号

用微信扫描二维码,
订阅宁皓网公众号。

240746680

用 QQ 扫描二维码,
加入宁皓网 QQ 群。

统计

15260
分钟
0
你学会了
0%
完成

社会化网络

关于

微信订阅号

扫描微信二维码关注宁皓网,每天进步一点