使用@hapijs/lab测试Hapi服务器时,如何避免创建多个数据库连接?
解决Hapi多测试文件重复创建数据库连接的问题
这个问题我之前在Hapi项目的测试阶段也遇到过,给你几个经过验证的解决方案,都能有效避免重复数据库连接的警告:
方案一:全局复用服务器实例
核心思路是只初始化一次服务器和数据库连接,所有测试文件共享这个实例,避免每个测试文件都重新创建。
实现步骤:
编写一个测试辅助文件,比如
test/helpers/server.js,封装服务器的创建和清理逻辑,确保单例:let serverInstance = null; // 获取单例服务器 async function getTestServer() { if (!serverInstance) { // 引入你的服务器创建函数 serverInstance = await require('../../server').createServer(); } return serverInstance; } // 清理服务器和数据库连接 async function cleanupTestServer() { if (serverInstance) { await serverInstance.stop(); // 这里加上数据库连接的关闭逻辑,比如你的pg-promise实例的end方法 const db = require('../../db'); await db.$pool.end(); serverInstance = null; } } module.exports = { getTestServer, cleanupTestServer };在测试的全局钩子中初始化和清理(可以放在一个统一的测试入口文件,比如
test/index.js,或者每个测试文件的顶部):const { lab, before, after } = require('@hapi/lab'); const { getTestServer, cleanupTestServer } = require('./helpers/server'); let server; // 所有测试开始前只初始化一次服务器 before(async () => { server = await getTestServer(); }); // 所有测试结束后清理资源 after(async () => { await cleanupTestServer(); }); // 导出server供其他测试文件使用 module.exports = { server };各个测试文件直接导入这个共享的server实例:
const { server } = require('./index'); const { it, describe } = require('@hapi/lab'); const { expect } = require('@hapi/code'); describe('API路由测试', () => { it('返回正确数据', async () => { const res = await server.inject({ method: 'GET', url: '/api/test' }); expect(res.statusCode).to.equal(200); }); });
方案二:配置数据库连接池
如果使用pg-promise,可以通过配置连接池让多个请求复用连接,而不是创建新的连接对象,从根源上消除重复连接警告。
修改你的数据库初始化代码:
const pgp = require('pg-promise')({ pool: { max: 5, // 连接池最大连接数 min: 1, // 保持的最小空闲连接数 idleTimeoutMillis: 30000 // 空闲连接超时时间 } }); // 初始化数据库连接(只会创建一个连接池) const db = pgp(process.env.DATABASE_URL); module.exports = db;
这样即使多个测试文件初始化服务器,pg-promise会自动复用连接池中的连接,不会创建重复的数据库对象。
方案三:Mock数据库连接(单元测试场景)
如果是单元测试,不需要连接真实数据库,可以用mock工具模拟数据库操作,既避免连接问题,又让测试更高效。
比如用sinon mock你的数据库查询方法:
const sinon = require('sinon'); const db = require('../../db'); const { it, describe, before, after } = require('@hapi/lab'); describe('单元测试:用户路由', () => { let queryStub; before(() => { // 模拟数据库查询返回 queryStub = sinon.stub(db, 'query').resolves({ rows: [{ id: 1, name: 'Test User' }] }); }); after(() => { // 恢复原方法 queryStub.restore(); }); it('获取用户列表成功', async () => { const server = await require('../../server').createServer(); const res = await server.inject({ method: 'GET', url: '/api/users' }); expect(res.statusCode).to.equal(200); expect(queryStub.calledOnce).to.be.true; }); });
也可以用pg-mem创建内存数据库,模拟真实数据库的行为,适合需要测试SQL逻辑的场景。
内容的提问来源于stack exchange,提问作者ekorolev
相关产品推荐
相关产品推荐

