【nest】nest+jest单元测试规范
版本:v1.0
适用范围:NestJS/nodejs企业后端项目
目标:提高可维护性、可测试性、系统稳定性
1. 测试总体要求
项目必须包含 Unit Test(单元测试)、E2E Test(端到端测试)。
必须使用 Jest 作为统一测试框架。
所有业务逻辑必须可测试、可 Mock。
合并进主分支前必须通过:
所有测试用例
全部覆盖率阈值
所有 linter & formatter 检查
覆盖率要求:
2. 测试目录与文件规范
src/
modules/
user/
user.module.ts
user.controller.ts
user.service.ts
__test__/
user.controller.spec.ts
user.service.spec.ts
user.module.spec.ts
test/
e2e/
app.e2e-spec.ts
jest.config.ts
规则:
单元测试统一放在:
/**/__test__/*.spec.ts不允许在根目录随意出现
.spec.tsE2E 测试统一放在:
/test/e2e/*单测文件命名:
xxx.controller.spec.tsxxx.service.spec.tsxxx.module.spec.ts
3. Mock(模拟)使用规范
3.1 必须 Mock 的内容
Service(用于 Controller 测试)
Repository(任何数据库行为)
第三方 SDK(OSS/S3/Redis/COS)
外部 API / RPC
全局提供者(JWT、CacheManager)
3.2 Mock 写法统一规范
不得在每个测试中重复写 mock
→ 必须在 beforeEach 或工厂函数中统一管理。
3.3 Mock 工具推荐
jest.fn()
jest.spyOn()
useValue: { ...mocks }
3.4 全局 Mock
在 test/setup.ts:
jest.mock('ioredis');
jest.mock('@nestjs/jwt');4. 模块(Module)测试规范
Module 测试验证的是 “装配正确性”:
必须测试:
Module 能否编译成功
Controller 是否被正确挂载
Provider 是否可实例化
动态模块参数是否生效
exports 是否能被其他模块引用
示例:
it('UserModule should be defined', () => {
expect(module).toBeDefined();
});5. 控制器(Controller)测试规范
Controller 主要关注行为,不关注业务逻辑。
必须测试:
示例:
it('should call service.create with dto', async () => {
await controller.create(dto);
expect(service.create).toHaveBeenCalledWith(dto);
});6. 服务(Service)测试规范
Service 是单测最核心的部分。
必须覆盖:
业务逻辑
必要的分支逻辑
边界条件
依赖的 repository mock 调用
第三方服务 mock 调用
异常抛出逻辑
示例:
it('should throw when user not found', async () => {
repo.findOne.mockResolvedValue(null);
await expect(service.findUser(1)).rejects.toThrow(NotFoundException);
});
7. 守卫(Guard)测试规范
必须测试:
canActivate()的返回逻辑带有权限判断的 Guard 必须测试用户权限链路
拒绝访问时的错误类型是否正确
示例:
it('should throw UnauthorizedException', () => {
context.switchToHttp().getRequest.mockReturnValue({ user: null });
expect(() => guard.canActivate(context)).toThrow(UnauthorizedException);
});8. 管道(Pipe)测试规范
必须测试:
transform()数据转换正常无效输入抛出正确的异常
类型转换逻辑正确
示例:
it('should throw BadRequestException on invalid id', () => {
expect(() => pipe.transform('abc')).toThrow(BadRequestException);
});
9. 拦截器(Interceptor)测试规范
必须测试:
是否调用
handler.handle()对返回值包装逻辑
日志、耗时、cache 行为是否正确
示例:
expect(mockNext.handle).toHaveBeenCalled();
10. 异常过滤器(Filter)测试规范
必须测试:
正确捕获异常
正确返回 HTTP 状态码
响应体格式一致性
11. E2E 测试规范
E2E 用于验证实际 API 行为。
必须覆盖:
登录流程
鉴权(JWT、角色权限)
请求参数校验
统一响应格式
全局拦截器/Filter 行为
主要功能链路(创建→查询→更新→删除)
示例:
return request(app.getHttpServer())
.get('/users')
.set('Authorization', 'Bearer testToken')
.expect(200);
12. 覆盖率要求
在 jest.config.js 配置:
coverageThreshold: {
global: {
statements: 80,
branches: 70,
functions: 80,
lines: 80,
},
},
13. CI 测试要求
CI 中必须满足:
所有测试通过
覆盖率通过
不允许存在
.only测试Snapshot 必须同步更新
eslint/prettier 校验必须通过
运行脚本:
npm run test:cov
14. 团队协作规范
所有新功能必须配套对应测试
重构必须更新测试
禁止依赖测试顺序
Mock 必须集中管理,不能散落在代码中
不允许访问真实数据库、真实 Redis(除 E2E)
15. 禁止的反模式
❌ 单测中访问数据库
❌ 单测中调用真实外部 API
❌ 在 Controller 单测中跑业务逻辑
❌ 使用复杂 mock 数据
❌ 测试相互依赖(顺序耦合)
❌ 在测试中使用魔法数字
❌ 无意义的“存在性测试”(除了 Module)
16. 附录:单测模板建议
可快速复制使用:
Controller 测试模板
Service 测试模板
Module 测试模板
Guard/Pipe/Interceptor/Filter 测试模板