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

使用Jest测试代码库函数时数据库连接异常解决方法

解决方案

首先明确两个核心问题的根因:

  1. 报role 'dan' does not exist是因为测试运行时db.js里的knex配置没有指定明确的数据库用户名,Postgres驱动默认取当前系统登录用户名dan作为连接角色,而你的本地PG实例中没有创建这个同名角色,直接触发连接错误。
  2. 跨测试文件无法复用全局db对象本质是Jest的模块沙箱+环境配置缺失问题,完全不需要每个测试文件重建连接,也不需要给所有业务函数新增db入参,下面两个方案都是生产环境验证过的成熟实践,改造成本极低:

方案1:环境隔离+全局连接管理(最推荐,零业务侵入)

这个方案不用改任何业务代码逻辑,只需要调整配置和测试初始化逻辑:

  • 第一步:改造db.js的配置逻辑,根据NODE_ENV环境变量动态加载对应环境的连接参数
    不要把连接配置硬编码,优先从环境变量读取,测试环境启动时自动注入测试库的连接信息(提前在本地PG建好测试库、对应账号并授权,从根源上避免默认取系统用户名当角色的问题),示例:
    // db.js
    const knex = require('knex');
    const config = {
      development: { /* 开发库配置 */ },
      test: {
        client: 'pg',
        connection: {
          host: process.env.DB_HOST || '127.0.0.1',
          // 明确指定测试库账号,不要留空让驱动取系统用户名
          user: process.env.DB_TEST_USER || 'test_user',
          password: process.env.DB_TEST_PWD || 'test123',
          database: process.env.DB_TEST_NAME || 'service_test'
        }
      },
      production: { /* 生产库配置 */ }
    };
    const db = knex(config[process.env.NODE_ENV || 'development']);
    module.exports = { db };
    
  • 第二步:在Jest配置中增加全局初始化/销毁逻辑,全测试周期复用同一个连接
    在jest.config.js中配置全局钩子:
    module.exports = {
      // 其他原有配置
      globalSetup: '<rootDir>/test/global-setup.js',
      globalTeardown: '<rootDir>/test/global-teardown.js',
      setupFilesAfterEnv: ['<rootDir>/test/setup-after-env.js']
    }
    
    三个钩子的职责非常清晰:
    • global-setup.js:跑所有测试前执行一次,设置NODE_ENV=test,执行数据库迁移、灌入基础测试种子数据
    • setup-after-env.js:每个测试文件加载前执行,注册全局afterEach钩子,每个用例跑完后清理对应业务表的测试数据,避免用例间数据污染
    • global-teardown.js:所有测试跑完后执行,关闭knex连接,销毁连接池,避免进程挂住
      这套配置跑完,所有业务代码里直接导入的db对象就是测试环境的合法连接,完全不会出现连接错误,也不需要每个测试文件重复创建连接实例。

方案2:Jest模块Mock(适合不想调整现有db配置的场景)

如果你暂时不想改db.js的原有逻辑,用Jest自带的模块Mock能力也能解决问题,同样不需要改业务函数的入参:

  • 在项目根目录的__mocks__文件夹下新建db.js文件,导出连接到测试库的knex实例:
    // __mocks__/db.js
    const knex = require('knex');
    const testDb = knex({
      client: 'pg',
      connection: {
        host: '127.0.0.1',
        user: 'test_user', // 提前在PG中创建该角色并授权测试库权限
        password: 'test123',
        database: 'service_test'
      }
    });
    module.exports = { db: testDb };
    
  • 在Jest配置中开启自动Mock,或者在需要测试的文件顶部手动加jest.mock('../path/to/db.js'),Jest会自动把所有业务代码中导入的db对象替换成你在mock里初始化的测试库连接,业务代码完全无感知。

常见误区避坑

  • 不要每个测试文件重复创建knex连接:单测跑的时候文件是隔离加载的,重复建连接会快速占满PG的连接数,还会拖慢测试速度,全局复用连接是标准做法。
  • 不要为了测试给所有业务函数加db入参:这种硬改函数签名的方式侵入性太强,后续维护成本极高,用环境隔离或者模块Mock的方式完全可以达到依赖注入的效果,不需要改业务代码。
  • 测试库一定要和开发库、生产库物理隔离,不要拿开发库跑测试,避免测试清理数据的时候误删正常业务数据。

内容的提问来源于stack exchange,提问作者Dan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 17:57:19