使用Jest和JavaScript模拟Redis时,RedisWrapper.mock.instances[0]始终为空
解决Jest中RedisWrapper.mock.instances为空的问题
问题根源
你当前的测试代码里,validateEmailWeb2接收的是RedisWrapper类而非实例化对象。Jest只有在类被new关键字实例化时,才会将实例存入mock.instances数组,直接传类不会触发实例创建,所以mock.instances[0]始终为空。
修复步骤
1. 调整测试代码,先实例化RedisWrapper
在测试中先创建RedisWrapper的模拟实例,再将实例传入validateEmailWeb2,而非传入类本身:
const {validateEmailWeb2} = require("../../plugins/ethermail_paywall"); const {PaywallConfigurationEnum} = require("../../enums/paywallEnum"); const RedisWrapper = require("../../helpers/redis-wrapper"); jest.mock("../../helpers/redis-wrapper") test('receiver with configuration: FILTER_HIGH_SECURITY_DOMAINS', async () => { const userReceiver = { config_web2: PaywallConfigurationEnum.FILTER_HIGH_SECURITY_DOMAINS, address: '0x261d37e08dc152e8b040bfff6278449910825f2b' } const domainSender = 'gmail' const prefix = 'paywall_domain_' // 实例化RedisWrapper,Jest会自动将实例存入mock.instances const redisInstance = new RedisWrapper(); const mockMongodb = jest.fn() // 传入实例而非类 expect(await validateEmailWeb2(userReceiver, userReceiver.address, domainSender, mockMongodb, redisInstance, prefix)).toBe(true) // 此时可正常访问mock实例,比如验证方法调用 expect(redisInstance.get).toHaveBeenCalled(); })
2. 确认validateEmailWeb2接收并使用Redis实例
要保证validateEmailWeb2内部是直接使用传入的Redis实例调用方法,而不是重新实例化RedisWrapper:
// 示例validateEmailWeb2的正确逻辑(参考) async function validateEmailWeb2(userReceiver, address, domainSender, mockMongodb, redisInstance, prefix) { // 使用传入的实例调用get方法 const cachedDomain = await redisInstance.get(`${prefix}${domainSender}`); // ...其他业务逻辑 return true; }
3. 可选:Mock Redis实例的方法返回值
如果需要控制Redis方法的返回结果,可在实例化后mock对应方法:
const redisInstance = new RedisWrapper(); // mock get方法返回指定值 redisInstance.get.mockResolvedValue('allowed-domain'); // mock set方法 redisInstance.set.mockResolvedValue('OK');
关键提示
- Jest的
mock.instances数组仅记录通过new MockClass()创建的实例,直接传类不会触发实例创建。 - 无需修改原文件的导出方式(
module.exports = RedisWrapper是CommonJS的标准写法,改成ES模块会导致项目其他模块报错)。
内容的提问来源于stack exchange,提问作者Luciano Pulido
相关产品推荐
相关产品推荐

