Express+Jest+Supertest多测试文件运行冲突问题求助
解决多测试文件并行时Prisma唯一约束冲突的方案
不用合并测试文件,按路由拆分测试是更合理的维护方式。针对你遇到的并行测试数据冲突问题,有以下几种可行的解决思路:
1. 让Jest串行运行测试文件
Jest默认并行执行多个测试文件,导致两个文件的beforeEach同时插入重复数据。可以强制Jest串行运行:
- 在
jest.config.js中添加配置:module.exports = { // ...其他配置 maxWorkers: 1, }; - 或者运行测试时添加参数:
jest --runInBand
这个方案最简单,但会降低测试执行速度,适合测试用例较少的项目。
2. 为每个测试生成唯一的测试数据
在初始化数据时,给用户名、邮箱等有唯一约束的字段添加随机后缀或标识,确保不同测试文件插入的数据不重复。比如:
// 生成随机后缀,避免重复 const randomSuffix = Math.random().toString(36).slice(2, 8); beforeEach(async () => { try { const [user, userTwo] = await Promise.all([ client.users.create({ data: { username: `foo-${randomSuffix}`, email: `bar-${randomSuffix}@baz.com`, pw: await bcrypt.hash("password", 10), }, }), client.users.create({ data: { username: `bar-${randomSuffix}`, email: `foo-${randomSuffix}@bar.com`, pw: await bcrypt.hash("password", 10), }, }), ]); await Promise.all([ client.boards.create({ data: { name: "one", creator_id: user.id, created_at: new Date(200000000000), members: { connect: user }, }, }), client.boards.create({ data: { name: "two", creator_id: userTwo.id, created_at: new Date(300000000000), members: { connect: userTwo }, }, }), client.boards.create({ data: { name: "three", creator_id: user.id, created_at: new Date(400000000000), members: { connect: [user, userTwo] }, }, }), ]); } catch (err) { console.error(err); return; } });
这个方案不影响测试并行速度,是最推荐的轻量解决方案。
3. 使用事务回滚隔离测试数据
利用数据库事务的特性,每个测试在独立事务中执行,测试结束后回滚事务,避免数据持久化到数据库。调整测试初始化逻辑如下:
let prismaTx; beforeEach(async () => { // 开启事务并执行初始化操作 prismaTx = await client.$transaction([ client.users.create({ data: { username: "foo", email: "bar@baz.com", pw: await bcrypt.hash("password", 10), }, }), client.users.create({ data: { username: "bar", email: "foo@bar.com", pw: await bcrypt.hash("password", 10), }, }), client.boards.create({ data: { name: "one", creator_id: (await client.users.findFirst({ where: { username: "foo" } })).id, created_at: new Date(200000000000), members: { connect: { username: "foo" } }, }, }), // ...其他看板初始化操作 ], { isolationLevel: 'Serializable' }); }); afterEach(async () => { // 回滚事务,清除测试数据 await client.$rollback(prismaTx); });
这种方式能完全隔离每个测试的数据库操作,不会出现数据污染,但需要熟悉数据库事务特性,部分场景下可能需要调整测试逻辑。
4. 为每个测试文件分配独立测试数据库
为每个Jest工作进程创建独立的测试数据库,彻底隔离不同测试文件的数据源。可以通过JEST_WORKER_ID环境变量区分不同进程,动态连接不同数据库:
// prisma/test-client.js const { PrismaClient } = require('@prisma/client'); const client = new PrismaClient({ datasources: { db: { url: `postgresql://user:pass@localhost:5432/test-db-${process.env.JEST_WORKER_ID || 0}`, }, }, }); module.exports = client;
测试前需要确保所有测试数据库都已创建,可以在测试脚本开头添加数据库初始化逻辑。这个方案隔离性最强,但配置和维护成本稍高。
内容的提问来源于stack exchange,提问作者Alphatron
相关产品推荐
相关产品推荐

