为什么我的 Prisma 单元测试调用我的数据库

问题描述 投票:0回答:3

我已经为在数据库中创建数据的函数编写了单元测试。我根据 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,
  })
})

鉴于这些文件与指南中的示例非常接近,我希望我编写的测试不会调用我的数据库。如何防止运行测试时调用我的数据库?

reactjs next.js jestjs prisma jest-mock-extended
3个回答
0
投票

也遇到过这个问题。我使用了在整个应用程序中使用的相同 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
中使用相同的客户端。


0
投票

这就是我所做的,它也与 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 的设置文件


0
投票

根据文档

关键是在

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 停止尝试连接到数据库。

© www.soinside.com 2019 - 2024. All rights reserved.