You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用@hapijs/lab测试Hapi服务器时,如何避免创建多个数据库连接?

解决Hapi多测试文件重复创建数据库连接的问题

这个问题我之前在Hapi项目的测试阶段也遇到过,给你几个经过验证的解决方案,都能有效避免重复数据库连接的警告:

方案一:全局复用服务器实例

核心思路是只初始化一次服务器和数据库连接,所有测试文件共享这个实例,避免每个测试文件都重新创建。

实现步骤:

  1. 编写一个测试辅助文件,比如 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 };
    
  2. 在测试的全局钩子中初始化和清理(可以放在一个统一的测试入口文件,比如 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 };
    
  3. 各个测试文件直接导入这个共享的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:59:15