Javascript 单元测试不受事件发射器约束的事件
我有下面的代码Javascript 单元测试不受事件发射器约束的事件,javascript,typescript,mocha.js,sinon,chai,Javascript,Typescript,Mocha.js,Sinon,Chai,我有下面的代码 private client: any; this.client = mqtt.connect(url, mqttOptions); this.client.on('message', (topic: string, message: string) => { console.log('came inside onMessage'); let ksiotMessage: KSIOTMessage; let receivedTopic:
private client: any;
this.client = mqtt.connect(url, mqttOptions);
this.client.on('message', (topic: string, message: string) => {
console.log('came inside onMessage');
let ksiotMessage: KSIOTMessage;
let receivedTopic: KSIOTTopic;
receivedTopic = getValue(topic);
ksiotMessage = {
ksiotTopic: receivedTopic,
payload: message
};
messageReceivedCallBack.onMessageReceived(ksiotMessage);
});
在这里,当mqtt客户机发出消息事件时,将触发一个匿名函数。我无法控制它,也就是说不是我将它绑定到事件发射器。此外,我无法添加计时器并等待此事件触发,因为我已经使用sinon模拟了客户端的连接。所以没有真正的联系。那么,如何手动发出此消息事件并查看是否调用了messageReceivedCallBack的onMessageReceived?我不熟悉Javascript中的单元测试。目前,我正在使用mocha和sinon来满足我的单元测试需求
请给出建议。首先,我不知道TypeScript,也不知道您的应用程序的内部结构,因此以下内容可能无法直接使用。但是,它可能会为您提供一些关于如何实现这些类型测试的想法 我提取了您的客户机代码(需要测试的代码): 在您的代码中,不清楚
messageReceivedCallBack
来自何处。因为您必须能够从Sinon访问它,所以它应该位于可导入模块中(但是,这确实取决于导入是缓存的,就像require()
,我不确定TS是否会这样做)
下面是我使用的一个简单的模拟:
// callbacks.js
module.exports = {
onMessageReceived(message) {}
};
最后,测试本身。它相当复杂,因为它需要做各种事情:
- 创建一个
子类,用于将原始EventEmitter
替换为MqttClient
- 各种函数和回调的存根
- 设置测试环境
// test.js
const mqtt = require('mqtt');
// The modules mentioned above.
const mqttModule = require('./mqtt-module');
const messageReceivedCallBack = require('./callbacks');
// Set up Sinon and Chai
const sinon = require('sinon');
const chai = require('chai');
let expect = chai.expect;
chai.use(require('sinon-chai'));
// Create a fake client for testing purposes.
const EventEmitter = require('events').EventEmitter;
class Client extends EventEmitter {}
// The test case.
describe('my test case', () => {
var mockClient;
beforeEach(() => {
mockClient = new Client();
// mqtt.connect() returns a fake client instance, with
// just enough logic to allow events to be emitted and
// received.
sinon.stub(mqtt, 'connect').returns(mockClient);
// Call the setup of our MQTT class (this will likely be
// entirely different in your case, but the idea is that
// it gets called _after_ `mqtt.connect()` gets stubbed.
mqttModule.setup();
});
afterEach(() => {
// Restore the original.
mqtt.connect.restore();
});
it('should call messageReceivedCallBack.onMessageReceived', () => {
// The message that we're going to pass.
let message = 'this is a test message';
// We want to stub messageReceivedCallBack.onMessageReceived()
sinon.stub(messageReceivedCallBack, 'onMessageReceived');
// Emit a `message` event on our mock client, which will trigger
// the `client.on('message', ...)` in your MQTT class.
mockClient.emit('message', 'topic', message);
// Test if the stub was called with the proper argument.
expect(messageReceivedCallBack.onMessageReceived).to.be.calledWith(message);
// Restore to the original function.
messageReceivedCallBack.onMessageReceived.restore();
});
});
大免责声明:我不知道TypeScript,也不知道应用程序的内部结构,所以下面的内容可能无法开箱即用。但是,它可能会为您提供一些关于如何实现这些类型测试的想法 我提取了您的客户机代码(需要测试的代码): 在您的代码中,不清楚
messageReceivedCallBack
来自何处。因为您必须能够从Sinon访问它,所以它应该位于可导入模块中(但是,这确实取决于导入是缓存的,就像require()
,我不确定TS是否会这样做)
下面是我使用的一个简单的模拟:
// callbacks.js
module.exports = {
onMessageReceived(message) {}
};
最后,测试本身。它相当复杂,因为它需要做各种事情:
- 创建一个
子类,用于将原始EventEmitter
替换为MqttClient
- 各种函数和回调的存根
- 设置测试环境
// test.js
const mqtt = require('mqtt');
// The modules mentioned above.
const mqttModule = require('./mqtt-module');
const messageReceivedCallBack = require('./callbacks');
// Set up Sinon and Chai
const sinon = require('sinon');
const chai = require('chai');
let expect = chai.expect;
chai.use(require('sinon-chai'));
// Create a fake client for testing purposes.
const EventEmitter = require('events').EventEmitter;
class Client extends EventEmitter {}
// The test case.
describe('my test case', () => {
var mockClient;
beforeEach(() => {
mockClient = new Client();
// mqtt.connect() returns a fake client instance, with
// just enough logic to allow events to be emitted and
// received.
sinon.stub(mqtt, 'connect').returns(mockClient);
// Call the setup of our MQTT class (this will likely be
// entirely different in your case, but the idea is that
// it gets called _after_ `mqtt.connect()` gets stubbed.
mqttModule.setup();
});
afterEach(() => {
// Restore the original.
mqtt.connect.restore();
});
it('should call messageReceivedCallBack.onMessageReceived', () => {
// The message that we're going to pass.
let message = 'this is a test message';
// We want to stub messageReceivedCallBack.onMessageReceived()
sinon.stub(messageReceivedCallBack, 'onMessageReceived');
// Emit a `message` event on our mock client, which will trigger
// the `client.on('message', ...)` in your MQTT class.
mockClient.emit('message', 'topic', message);
// Test if the stub was called with the proper argument.
expect(messageReceivedCallBack.onMessageReceived).to.be.calledWith(message);
// Restore to the original function.
messageReceivedCallBack.onMessageReceived.restore();
});
});
您的测试代码需要访问
this.client
和messageReceivedCallBack
。是这样吗?this.client从“mqtt.connect”行分配了一个值。因此,我将退还我自己的存根。我需要知道如何触发此连接事件,以便测试内部代码。由于我已经中断了connect方法,“message”事件不会自动触发。我需要手动启动它。我不知道如何:(您的测试代码需要访问this.client
和messageReceivedCallBack
。是这样吗?this.client从“mqtt.connect”行分配了一个值。因此,我将返回我自己的存根。我需要知道如何启动此连接事件,以便测试内部代码。由于我已中断了连接方法,“消息”事件将不会自动启动。我需要手动启动它。我不知道如何:(非常棒的解决方案伙伴!:)非常棒的解决方案伙伴!:)