Jest中实现所有测试文件仅初始化一次服务与数据库连接
解决多测试文件下数据库全局初始化与服务器共享问题
问题背景
项目包含多个测试文件,每个文件都重复实现beforeAll/afterAll来启动服务器、初始化数据库及终止连接。已通过测试环境不指定端口解决端口占用,但多文件运行时会触发数据库UniqueConstraintError,需要实现服务器与数据库的全局一次性初始化,同时保证测试用例能正常访问server调用API。
解决方案步骤
1. 配置全局初始化与清理脚本
利用测试框架(以Jest为例)的全局Setup/Teardown机制,实现仅执行一次的初始化和清理逻辑:
全局初始化脚本(tests/globalSetup.js)
const db = require('../service/pg'); const createServer = require('../service/server'); module.exports = async () => { // 初始化数据库连接并同步模型 const sequelize = await db.init(); // 创建并启动Hapi服务器 const server = await createServer(); await server.start(); // 将实例挂载到全局对象,供所有测试文件访问 global.testServer = server; global.sequelize = sequelize; };
全局清理脚本(tests/globalTeardown.js)
module.exports = async () => { // 停止服务器 await global.testServer.stop(); // 清理数据库并关闭连接 await global.sequelize.drop(); await global.sequelize.close(); };
更新Jest配置(jest.config.js)
module.exports = { globalSetup: './tests/globalSetup.js', globalTeardown: './tests/globalTeardown.js', // 保留其他原有配置 };
2. 改造数据库连接为单例模式
避免多次初始化数据库连接,在sequelize.js中实现单例:
const { Sequelize } = require('sequelize'); const env = require('./env'); // 替换为你的环境变量配置路径 let user_db; // 单例模式确保仅创建一个数据库连接实例 function getSequelizeInstance() { if (!user_db) { user_db = new Sequelize( env.dbName, env.user, env.password, { host: env.host, port: env.port, dialect: 'postgres', logging: false, } ); // 在此处添加模型定义... } return user_db; } module.exports = getSequelizeInstance();
3. 简化数据库初始化逻辑
修改db.js,确保模型同步仅在全局初始化时执行一次:
const sequelize = require('./sequelize'); async function init() { await sequelize.sync(); return sequelize; } module.exports = { init };
4. 简化测试文件代码
移除测试文件中重复的beforeAll/afterAll,直接使用全局挂载的server实例:
describe('testing...', () => { test('one + one = 2', async () => { const options = { method: 'POST', url: '/math', }; // 使用全局的testServer实例发起请求 const res = await global.testServer.inject(options); expect(1).toEqual(1); }); });
关键说明
- 全局脚本确保服务器和数据库仅初始化/清理一次,彻底避免重复操作导致的唯一约束冲突。
- 单例模式的数据库连接防止多文件重复创建连接实例。
- 测试文件直接复用全局server,无需重复启动,提升测试效率。
内容的提问来源于stack exchange,提问作者SunAns
相关产品推荐
相关产品推荐

