如何使用Jest mock MongoDB客户端的事件监听器?
实现方案
核心思路是在mock connect 方法的返回值时,保留事件回调的存储和触发能力,具体实现如下:
完整测试代码
const { ServiceBroker } = require('moleculer'); // 注意提前引入对应ServiceBroker依赖 test('should write error to console when mongo client emits error event', async () => { // mock console.error 用于后续断言 const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); const broker = new ServiceBroker({ logger: false }); broker.loadService(`${process.cwd()}/index.js`); const services = broker.services.filter( (service) => service.fullName === 'mongo' ); // 存储事件回调的对象 const eventCallbacks = {}; const connectSpy = jest.spyOn(services[0].client, 'connect'); connectSpy.mockResolvedValue({ db: jest.fn().mockReturnValue({ collection: jest.fn(), }), // 实现on方法,存储对应事件的回调 on: jest.fn((eventName, callback) => { if (!eventCallbacks[eventName]) { eventCallbacks[eventName] = []; } eventCallbacks[eventName].push(callback); }), // 实现emit方法,触发对应事件的所有回调 emit: jest.fn((eventName, ...args) => { if (eventCallbacks[eventName]) { eventCallbacks[eventName].forEach(cb => cb(...args)); } }) }); await broker.start(); expect(connectSpy).toHaveBeenCalled(); // 验证error事件已经被注册 expect(connectSpy.mock.results[0].value.on).toHaveBeenCalledWith('error', expect.any(Function)); // 模拟触发error事件 connectSpy.mock.results[0].value.emit('error'); // 断言控制台输出符合预期 expect(consoleErrorSpy).toHaveBeenCalledWith('MongoDB error'); // 恢复spy避免影响其他测试 consoleErrorSpy.mockRestore(); });
实现说明
- 在mock的connect返回值中新增
eventCallbacks对象用来存储所有注册的事件回调 - 重写
on方法,每当有事件被注册时就把对应的回调存到eventCallbacks中 - 新增
emit方法,调用时会取出对应事件的所有回调执行,以此模拟Mongo客户端的事件触发逻辑 - 通过监听
console.error的调用来验证错误日志是否正常输出
内容的提问来源于stack exchange,提问作者Kevin Landon
相关产品推荐
相关产品推荐

