【问题标题】:Asserting the behavior of an handler of an EventEmitter event断言 EventEmitter 事件的处理程序的行为
【发布时间】:2021-12-29 14:15:43
【问题描述】:

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

我正在用 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 客户端是从 EventEmitter 扩展而来的第三方库中的一个类。

我想创建一个测试,断言 sock.send 函数在“更新”事件的处理程序中只被调用一次。

这是我的方法:

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 | });

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

谢谢

【问题讨论】:

    标签: node.js unit-testing jestjs


    【解决方案1】:

    jest.mock()模拟后,在app.jsapp.spec.js文件中调用.wsClient().zmqSock()方法时,sockapp.js中的ws对象不同app.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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-24
      • 1970-01-01
      相关资源
      最近更新 更多