断言 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
文件中被调用时,sock
和 ws
中的对象 app.js
与 app.spec.js
中的对象不同。
{
wsClient: jest.fn(() => {
const EventEmitter = require("events")
const emitter = new EventEmitter()
return emitter;
})
}
每次调用.wsClient()
,都会创建一个新对象。
Emitter 只能侦听来自它自己的事件 emit
。解决方案是在模拟工厂中创建模拟 emitter
和 sock
对象。
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
我是开玩笑的新手,很抱歉,如果这是一个微不足道的问题,但我浏览了官方的开玩笑文档,但我找不到解决问题的方法。
我正在 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
文件中被调用时,sock
和 ws
中的对象 app.js
与 app.spec.js
中的对象不同。
{
wsClient: jest.fn(() => {
const EventEmitter = require("events")
const emitter = new EventEmitter()
return emitter;
})
}
每次调用.wsClient()
,都会创建一个新对象。
Emitter 只能侦听来自它自己的事件 emit
。解决方案是在模拟工厂中创建模拟 emitter
和 sock
对象。
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