断言 EventEmitter 事件的处理程序的行为

Asserting the behavior of an handler of an EventEmitter event

我是开玩笑的新手,很抱歉,如果这是一个微不足道的问题,但我浏览了官方的开玩笑文档,但我找不到解决问题的方法。

我正在 nodejs 中开发一个非常简单的应用程序,它使用来自 websocket 的数据并通过 zeromq 将其传播到下游到一组消费者。

代码如下:

app.js:

const initializer = require("./dependencyInitializer");

const sock = initializer.zmqSock();
const ws = initializer.wsClient();

ws.on('update', data => {
  sock.send([data.topic, JSON.stringify(data)]);
});

websocket 客户端是 class 来自 EventEmitter 扩展的第三方库。

我想创建一个测试,断言 sock.send 函数在 'update' 事件的处理程序中被调用了一次。

这是我的方法:

app.spec.js:

const ws = require("./app");
const initializer = require("./dependencyInitializer");

jest.mock("./dependencyInitializer", () => {
    return {
        wsClient: jest.fn(() => {
            const EventEmitter = require("events")
            const emitter = new EventEmitter()

            return emitter;
        }),
        zmqSock: jest.fn(() => {
            return {
                send: jest.fn()
            }
        })
    }
});
describe('on message received from websocket',() => {
    it('should pass it to zmq', () => {
        const data = {result: "ok"};

        expect(initializer.wsClient).toHaveBeenCalledTimes(1);
        expect(initializer.zmqSock).toHaveBeenCalledTimes(1);

        const _sock = initializer.zmqSock();
        const _ws = initializer.wsClient();
        _ws.emit("update", data);
        expect(_sock.send).toHaveBeenCalledTimes(1);
    });
});

测试失败,出现以下情况:

on message received from websocket › should pass it to zmq

    expect(jest.fn()).toHaveBeenCalledTimes(expected)

    Expected number of calls: 1
    Received number of calls: 0

      28 |         const _ws = initializer.wsClient();
      29 |         _ws.emit("update", data);
    > 30 |         expect(_sock.send).toHaveBeenCalledTimes(1);
         |                            ^
      31 |     });
      32 | });

我不确定我是否走在正确的道路上,我想了解开发这样的测试的最佳方法是什么。

谢谢

在被jest.mock()模拟后,当.wsClient().zmqSock()方法在app.js文件和app.spec.js文件中被调用时,sockws 中的对象 app.jsapp.spec.js 中的对象不同。

{
  wsClient: jest.fn(() => {
    const EventEmitter = require("events")
    const emitter = new EventEmitter()
    return emitter;
  })
}

每次调用.wsClient(),都会创建一个新对象。

Emitter 只能侦听来自它自己的事件 emit。解决方案是在模拟工厂中创建模拟 emittersock 对象。

app.js:

const initializer = require('./dependencyInitializer');

const sock = initializer.zmqSock();
const ws = initializer.wsClient();

ws.on('update', (data) => {
  sock.send([data.topic, JSON.stringify(data)]);
});

module.exports = { sock, ws };

app.test.js:

const app = require('./app');
const initializer = require('./dependencyInitializer');

jest.mock(
  './dependencyInitializer',
  () => {
    const EventEmitter = require('events');
    const emitter = new EventEmitter();
    const mSock = { send: jest.fn() };
    return {
      wsClient: jest.fn(() => emitter),
      zmqSock: jest.fn(() => mSock),
    };
  },
  { virtual: true }
);
describe('on message received from websocket', () => {
  it('should pass it to zmq', () => {
    const data = { result: 'ok' };

    expect(initializer.wsClient).toHaveBeenCalledTimes(1);
    expect(initializer.zmqSock).toHaveBeenCalledTimes(1);

    const _sock = initializer.zmqSock();
    const _ws = initializer.wsClient();

    // check if they have same reference
    expect(app.sock).toBe(_sock);
    expect(app.ws).toBe(_ws);

    _ws.emit('update', data);
    expect(_sock.send).toHaveBeenCalledTimes(1);
  });
});

测试结果:

 PASS  examples/70024105/app.test.js (9.279 s)
  on message received from websocket
    ✓ should pass it to zmq (2 ms)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |      100 |     100 |     100 |                   
 app.js   |     100 |      100 |     100 |     100 |                   
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        10.112 s