我已经为在数据库中创建数据的函数编写了单元测试。我根据 Prisma 单元测试 指南创建了测试,根据该指南,模拟 Prisma 客户端应该阻止对我的数据库的调用。然而,当我运行测试时,我的数据库被调用并实际创建了数据。
要执行测试,有几个相关文件。
在
prsma.js
中,我实例化了 Prisma 客户端。
import { PrismaClient } from "@prisma/client"
let prisma
if(process.env.NODE_ENV === 'production') {
prisma = new PrismaClient()
} else {
if(!global.prisma) {
global.prisma = new PrismaClient()
}
prisma = global.prisma
}
export default prisma
在
singleton.ts
中,我告诉 Jest 模拟默认导出。
import { PrismaClient } from '@prisma/client'
import { mockDeep, mockReset, DeepMockProxy } from 'jest-mock-extended'
import prisma from './client'
jest.mock('./client', () => ({
__esModule: true,
default: mockDeep<PrismaClient>(),
}))
beforeEach(() => {
mockReset(prismaMock)
})
export const prismaMock = prisma as unknown as DeepMockProxy<PrismaClient>
在
schema.prisma
中,我为我要测试的表创建模型。
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Test {
id Int @id @default(autoincrement())
}
在
functions-without-context.ts
中,我模拟了在Test
表中创建数据的过程。
import prisma from './client'
interface CreateTest {
description: string
}
export async function createTest(test: CreateTest) {
return await prisma.test.create({
data: test,
})
}
最后,在
with-singleton.ts
中,我创建了实际测试。
import { createTest, updateTest } from '../lib/mock/functions-without-context'
import { prismaMock } from '../lib/mock/singleton'
it('should create new data ', async () => {
const test = {
id: 1,
}
prismaMock.test.prismaMock.mockResolvedValue(test)
await expect(createTest(test)).resolves.toEqual({
id: 1,
})
})
鉴于这些文件与指南中的示例非常接近,我希望我编写的测试不会调用我的数据库。如何防止运行测试时调用我的数据库?
也遇到过这个问题。我使用了在整个应用程序中使用的相同 prisma 客户端,并且它可以正确模拟。
import { PrismaClient } from '@prisma/client'
import { mockDeep, mockReset, DeepMockProxy } from 'jest-mock-extended'
import prisma from './prsma.js' //In your case
jest.mock('./prsma.js', () => ({ //In your case
__esModule: true,
default: mockDeep<PrismaClient>(),
}))
beforeEach(() => {
mockReset(prismaMock)
})
export const prismaMock = prisma as unknown as DeepMockProxy<PrismaClient>
如果您在
./lib/prisma.ts
中已有用于调用数据库的导出的 prisma 客户端,请在 .singleton.ts
中使用相同的客户端。
这就是我所做的,它也与 DI 完美配合(只需将 PrismaClient 的容器注册为模拟 Prisma)
import { PrismaClient } from '@prisma/client';
const mockPrismaDeep = () => {
const actualPrisma = jest.requireActual('@prisma/client');
const mockPrisma: PrismaClient = {
...new actualPrisma.PrismaClient(),
$connect: jest.fn().mockImplementation(() => Promise.resolve()),
$disconnect: jest.fn().mockImplementation(() => Promise.resolve()),
$transaction: jest.fn().mockImplementation(async callback => {
const mockPrismaTransaction = {
...mockPrisma
};
await callback(mockPrismaTransaction);
})
};
jest.mock('@prisma/client', () => {
return {
...actualPrisma, //We want all the actual prisma stuff
PrismaClient: jest.fn(() => mockPrisma)
};
});
};
mockPrismaDeep();
我已将其设置为 env 之后 jest 的设置文件
根据文档:
关键是在
setupFilesAfterEnv
中从jest.config.ts
调用以下内容:
import { PrismaClient } from '@prisma/client'
import { mockDeep, mockReset, DeepMockProxy } from 'jest-mock-extended'
import prisma from './client'
jest.mock('./client', () => ({
__esModule: true,
default: mockDeep<PrismaClient>(),
}))
beforeEach(() => {
mockReset(prismaMock)
})
export const prismaMock = prisma as unknown as DeepMockProxy<PrismaClient>
这看似不那么重要,但却至关重要。执行此操作后,您将看到 Prisma 停止尝试连接到数据库。