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

Jest检测到Redis连接未关闭及Mock后断开失效问题求助

解决Jest Mock Redis后Open Handle未关闭的问题

问题背景

测试displayVouchers函数时,因为该函数所在模块依赖的selectedVoucherHandlers引入了Redis连接,导致Jest用--detectOpenHandles运行时总是提示存在未关闭的Timeout类型open handle。最初直接导入Redis实例并在afterAll里调用disconnect()能解决,但给Redis加Mock后,这个方法就失效了。

解决方案

1. 手动Mock Redis并添加disconnect方法

自动生成的Mock对象默认没有disconnect方法,需要手动定义Mock时补上这个方法,让afterAll里的调用能正常执行:

// 先手动Mock Redis模块
jest.mock('../config/redis', () => {
  const mockRedis = {
    hset: jest.fn().mockResolvedValue(1),
    // 模拟disconnect方法,空实现即可
    disconnect: jest.fn()
  };
  return mockRedis;
});

// 再导入所需模块和Mock后的Redis
const { displayVouchers } = require('../Buy Raffle Voucher/index');
const { onAmountSelected } = require('../Buy Raffle Voucher/selectedVoucherHandlers');
const redis = require('../config/redis');

afterAll(() => {
  redis.disconnect();
});

describe("All buy-raffle-voucher here", () => {
    it('should return available vouchers', () => {
        expect(displayVouchers()).toBe("Select a voucher amount\n1. N200\n2. N500\n3. N1000");
    }); 

    it("should return recipient types", async () => {
        const result = await onAmountSelected(['0', '1'], 'dasdjl')
        redis.hset.mockResolvedValueOnce(1);
        expect(redis.hset).toHaveBeenCalled();
        expect(result).toBe('CON Voucher is for \n 1 Self \n 2 Others'); 
    });
});

2. 调整导入顺序,确保Mock优先生效

原来的代码先导入了Redis再调用jest.mock,这会导致导入的是真实的Redis实例而非Mock对象。把jest.mock放在所有导入语句之前,就能保证后续导入的Redis是Mock版本:

// 先执行Mock
jest.mock('../config/redis');

// 再导入模块
const { displayVouchers } = require('../Buy Raffle Voucher/index');
const { onAmountSelected } = require('../Buy Raffle Voucher/selectedVoucherHandlers');
const redis = require('../config/redis');

// 给自动Mock的Redis补充disconnect方法
redis.disconnect = jest.fn();

afterAll(() => {
  redis.disconnect();
});

describe("All buy-raffle-voucher here", () => {
    // ...测试用例不变
});

3. 在Redis连接文件中区分测试环境

直接在redis.js里判断环境,测试环境下导出Mock对象,避免创建真实连接:

const Redis = require('ioredis');

let redis;

if (process.env.NODE_ENV === 'test') {
  // 测试环境用Mock对象
  redis = {
    hset: jest.fn().mockResolvedValue(1),
    disconnect: jest.fn()
    // 其他用到的Redis方法都在这里模拟
  };
} else {
  // 生产/开发环境创建真实连接
  redis = new Redis();
  redis.on('connect', () => {
    console.log('Redis connection successful');
  });
}

module.exports = redis;

这种方式一劳永逸,测试时根本不会建立真实Redis连接,自然不会有open handle问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 22:10:36