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
相关产品推荐
相关产品推荐

