rin*_*ogo 14 jestjs nestjs prisma
我见过的大多数关于如何测试 Prisma 注入的 NestJS 服务的示例(例如在 参考资料prisma-sample中testing-nestjs)都是“端到端”测试。他们实际上访问数据库,执行实际查询,然后在必要时回滚结果。
对于我当前的需求,我想实现较低级别的“集成”测试。
作为其中的一部分,我想从等式中删除 Prisma。我希望重点关注服务的功能,而不是数据库内数据的状态以及 Prisma 返回数据的能力。
这种方法的一大优点是它消除了为特定测试精心设计“设置”查询和“拆卸”/重置操作的需要。相反,我想简单地手动指定我们期望 Prisma 返回的内容。
在由 NestJS、Prisma 和 Jest 组成的环境中,我应该如何实现这一点?
更新:testing-nestjs 项目的作者在评论中指出该项目确实有数据库模拟的示例。看起来很好!其他人可能仍然有兴趣查看我链接到的要点,因为它包含一些其他有用的功能。
rin*_*ogo 16
要获取对服务的 prisma 实例的引用,请使用:
prisma = module.get<PrismaService>(PrismaService)
Run Code Online (Sandbox Code Playgroud)
然后,假设您的函数调用prisma.name.findMany(),您可以使用jest.fn().mockReturnValueOnce()来模拟(手动指定)Prisma 的下一个返回值:
prisma.name.findMany = jest.fn().mockReturnValueOnce([
{ id: 0, name: 'developer' },
{ id: 10, name: 'architect' },
{ id: 13, name: 'dog walker' }
]);
Run Code Online (Sandbox Code Playgroud)
(当然,您可以更改prisma.name.findMany上面的代码以匹配您调用的任何函数。)
然后,调用您正在测试的服务上的函数。例如:
expect(await service.getFirstJob("steve")).toBe('developer');
Run Code Online (Sandbox Code Playgroud)
就是这样!完整的代码示例可以在这里找到。
Dav*_*ira 11
您还可以使用包来模拟整个 Prisma 客户端,这是 Prisma 官方文档jest-mock-extended中使用的方法。
假设您已经按照 NestJS文档PrismaService中的建议创建了一个,测试将是:
import { Test, TestingModule } from '@nestjs/testing'
import { PrismaClient } from '@prisma/client'
import { mockDeep, DeepMockProxy } from 'jest-mock-extended'
describe('UserService', () => {
let service: UserService;
let prisma: DeepMockProxy<PrismaClient>;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [UserService, PrismaService],
})
.overrideProvider(PrismaService)
.useValue(mockDeep<PrismaClient>())
.compile();
service = module.get(UserService);
prisma = module.get(PrismaService);
});
it('returns users', () => {
const testUsers = [];
prisma.user.findMany.mockResolvedValueOnce(testUsers);
expect(service.findAll()).resolves.toBe(testUsers);
});
});
Run Code Online (Sandbox Code Playgroud)
这种方法的好处之一是您可以使用Jest Mock 函数 API轻松地在 Prisma 客户端上进行模拟。
Nest.js 提供了一个用于模拟整个服务的 API,Prisma 只是其中之一。
为简单起见,我们假设我们直接从应用程序控制器访问 prisma。
import { Controller, Get } from '@nestjs/common';
import { DbService } from 'src/db/db.service';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(
private readonly appService: AppService,
private readonly prisma: DbService,
) {}
@Get()
async getHello(): Promise<string> {
const result = await this.prisma.user.findMany();
console.log('result', result);
return this.appService.getHello();
}
}
Run Code Online (Sandbox Code Playgroud)
那么测试将是:
describe('AppController', () => {
let appController: AppController;
const mockPrisma = {
user: { findMany: () => Promise.resolve([]) },
};
beforeEach(async () => {
const app: TestingModule = await Test.createTestingModule({
controllers: [AppController],
providers: [AppService, DbService],
})
.overrideProvider(DbService)
.useValue(mockPrisma)
.compile();
appController = app.get<AppController>(AppController);
});
describe('root', () => {
it('should return "Hello World!"', () => {
expect(appController.getHello()).resolves.toBe('Hello World!');
});
});
});
Run Code Online (Sandbox Code Playgroud)
DbService 是以下文件(如此处建议的https://docs.nestjs.com/recipes/prisma#use-prisma-client-in-your-nestjs-services):
@Injectable()
export class DbService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
await this.$connect();
}
async enableShutdownHooks(app: INestApplication) {
this.$on('beforeExit', async () => {
await app.close();
});
}
}
Run Code Online (Sandbox Code Playgroud)
请务必使用 的实例DbService,而不是 string 'DbService'。否则仍然会进行数据库调用并且测试失败。
| 归档时间: |
|
| 查看次数: |
16855 次 |
| 最近记录: |