当我在一个独立的环境中运行测试时,Prisma ORM客户端使用了错误的数据库URL
我在用vitest运行端到端测试。计划为测试创建一个不同的PostgreSQL模式。为了自动配置这个模式,我已经按vitest的文档这么做了:
// vitest-environment-prisma.ts
import { execSync } from 'node:child_process'
import { randomUUID } from 'node:crypto'
import type { Environment } from 'vitest/environments'
import 'dotenv/config'
function makeDatabaseUrl(schema: string) {
const connectionString = process.env.DATABASE_URL
if (!connectionString) {
throw new Error('DATABASE_URL environment variable missing.')
}
const databaseUrl = new URL(connectionString)
databaseUrl.searchParams.set('schema', schema)
return databaseUrl.toString()
}
export default <Environment> {
name: 'prisma',
viteEnvironment: 'ssr',
setup: async function () {
const schema = randomUUID()
process.env.DATABASE_URL = makeDatabaseUrl(schema)
execSync('npx prisma migrate deploy')
return {
teardown: async function () {
},
}
},
}
现在,我尝试运行到目前为止唯一的端到端测试:
import { app } from '@/app.js'
import { prisma } from '@/lib/prisma.js'
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
describe('Register User (e2e)', () => {
beforeAll(async () => {
await app.ready()
})
afterAll(async () => {
await app.close()
})
it('Should register user', async () => {
const a = await prisma.$queryRaw`SELECT current_schema();`
console.log(a)
const user = {
name: 'John Doe',
email: '[email protected]',
password: '12435djdj!',
}
const response = await app.inject({
method: 'POST',
path: '/users',
body: user,
})
expect(response.statusCode).toEqual(201)
})
})
我一直收到一个错误,说用户已经存在。这是我的应用的行为。不过,由于我应该使用一个干净的数据库模式,里面不应该有任何东西。所以我增加了那个“a”的console.log,结果是: [ { current_schema: 'public' } ]
所以Prisma仍然使用默认的模式,尽管我把process.env.DATABASE_URL改成了一个全新的模式。
我到底做错了什么? 编辑:这是我的lib/prisma.ts文件:(我不知道怎么排版)
import { env } from '@/env/index.js'
import { PrismaClient } from '../../prisma/generated/prisma/client.js'
import { PrismaPg } from '@prisma/adapter-pg'
export const prisma = new PrismaClient({
adapter: new PrismaPg({
connectionString: env.DATABASE_URL,
}),
log: env.NODE_ENV === 'development' ? ['query'] : [],
})
解决方案
你创建Prisma过早了。
env.DATABASE_URL 在模块加载时读取一次,因此你的客户端一直使用原始URL,尽管你的Vitest环境后续会改变 process.env.DATABASE_URL。
与此同时,prisma migrate deploy 确实使用了新的URL,导致不匹配。
修复:
- 不要使用预构建的单例
- 这里不要使用
env.DATABASE_URL - 在设置
process.env.DATABASE_URL之后再创建Prisma
export function makePrisma() {
return new PrismaClient({
adapter: new PrismaPg({
connectionString: process.env.DATABASE_URL!,
}),
})
}
然后在你的测试/应用中,在设置好模式后再初始化它。
如果仍然命中 public,你很可能遇到了一个已知的 @prisma/adapter-pg 模式问题。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。