NestAPI单元测试失败:findAll返回空数组与预期不符
问题
我正在为我的NestAPI编写单元测试。我的service.ts中有如下代码:
findAll(): Promise<Users[]> { return prisma.users.findMany(); }
在service.spec.ts中,我定义了测试数据:
const usersMany = [ { username: 'user1', name: 'User One', password: '123', email: 'user1@test.com', tasks: [], }, { username: 'user2', name: 'User Two', password: '456', email: 'user2@test.com', tasks: [], } ]
随后编写了findAll()的测试用例:
describe('findAll', () => { it('should return all users', async () => { const usersAll = await service.findAll(); expect(usersAll).toEqual(usersMany); }); });
但运行测试时出现错误,实际返回空数组,与预期的用户列表不符:
- Expected - 23 + Received + 1 - Array [ - Object { - "email": "user1@test.com", - "name": "User One", - "password": "123", - "tasks": Array [], - "username": "user1", - }, - Object { - "email": "user2@test.com", - "name": "User Two", - "password": "456", - "tasks": Array [], - "username": "user2", - }, - ] + Array []
我是单元测试新手,想知道测试失败的原因。
原因与解决方法
测试失败的核心原因是你直接调用了真实的Prisma客户端,而测试环境的数据库里没有预先插入usersMany中的测试数据,所以findMany()返回空数组。单元测试应该隔离依赖,不需要连接真实数据库,正确的做法是Mock Prisma客户端的users.findMany方法。
具体步骤如下:
- 在测试文件中Mock Prisma服务
在service.spec.ts里,需要先Mock PrismaModule,确保Service依赖的是Mock后的Prisma客户端,而不是真实实例。示例代码:import { Test, TestingModule } from '@nestjs/testing'; import { UsersService } from './users.service'; import { PrismaService } from '../prisma/prisma.service'; describe('UsersService', () => { let service: UsersService; let prisma: PrismaService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ UsersService, { provide: PrismaService, useValue: { users: { findMany: jest.fn(), // Mock findMany方法 }, }, }, ], }).compile(); service = module.get<UsersService>(UsersService); prisma = module.get<PrismaService>(PrismaService); }); - 在测试用例中指定Mock方法的返回值
修改findAll的测试用例,让Mock的findMany返回你定义的usersMany数据:describe('findAll', () => { it('should return all users', async () => { // 设定Mock方法的返回值 jest.spyOn(prisma.users, 'findMany').mockResolvedValue(usersMany); const usersAll = await service.findAll(); expect(usersAll).toEqual(usersMany); // 额外验证:确保findMany被调用了一次 expect(prisma.users.findMany).toHaveBeenCalledTimes(1); }); }); - (可选)如果需要用真实数据库测试(集成测试)
如果你想验证真实数据库的查询逻辑,那需要在测试前初始化数据库并插入测试数据,测试后清理数据。可以使用Prisma的测试数据库,配合beforeEach和afterEach钩子:
但注意这属于集成测试范畴,单元测试更推荐使用Mock隔离依赖,保证测试速度和稳定性。beforeEach(async () => { // 插入测试数据 await prisma.users.createMany({ data: usersMany }); }); afterEach(async () => { // 清理数据 await prisma.users.deleteMany(); });
内容的提问来源于stack exchange,提问作者AnonymousGeese
相关产品推荐
相关产品推荐

