我编写的Nest.js项目TasksService单元测试是否正确?
你的测试写法存在核心错误,属于无效测试
- 错误Mock了被测对象本身:你将需要测试的
TasksService直接替换为了Mock对象,所有测试用例运行时调用的都是你手动编写的Mock方法,完全没有执行tasks.service.ts里的真实业务逻辑,测试结果没有任何参考价值 - 没有Mock正确的依赖项:
getTaskById方法的核心依赖是注入的TaskModel,你应该Mock的是TaskModel的findById方法,通过控制该方法的返回值,触发真实Service逻辑的不同分支做验证 - 存在测试用例污染风险:你在第二个用例中直接修改了全局Mock对象的返回值,没有做用例间的Mock重置操作,会影响后续其他测试用例的运行结果
修正后的测试代码
以下是针对Mongoose场景的标准单元测试写法,如果你使用其他ORM,替换对应的Model注入token即可:
import { Test, TestingModule } from '@nestjs/testing'; import { TasksService } from './tasks.service'; import { getModelToken } from '@nestjs/mongoose'; import { NotFoundException } from '@nestjs/common'; const mockTask = { _id: '613e4135ea46be481c2d88b2', name: 'Task 1', description: 'Go to school', }; describe('TasksService', () => { let service: TasksService; let taskModel: any; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ TasksService, { provide: getModelToken('Task'), useValue: { findById: jest.fn(), }, }, ], }).compile(); service = module.get<TasksService>(TasksService); taskModel = module.get(getModelToken('Task')); // 每次测试前清空Mock调用记录和返回值,避免用例污染 jest.clearAllMocks(); }); it('should be defined', () => { expect(service).toBeDefined(); }); describe('getTaskById', () => { it('传入存在的任务ID时,应返回对应的任务数据', async () => { taskModel.findById.mockResolvedValue(mockTask); const result = await service.getTaskById(mockTask._id); expect(taskModel.findById).toHaveBeenCalledWith(mockTask._id); expect(result).toEqual(mockTask); }); it('传入不存在的任务ID时,应抛出NotFoundException', async () => { taskModel.findById.mockResolvedValue(null); await expect(service.getTaskById('invalid-id')).rejects.toThrow( new NotFoundException('Task not found'), ); expect(taskModel.findById).toHaveBeenCalledWith('invalid-id'); }); }); });
修正后的代码会真实执行Service的业务逻辑,通过控制依赖的返回值覆盖所有代码分支,同时保证测试用例之间相互独立。
内容的提问来源于stack exchange,提问作者robert_45
相关产品推荐
相关产品推荐

