[英]Stub a ES6 EventEmitter class function
我有一个扩展EventEmitter的依赖项类,我需要测试使用此依赖项的函数如何根据触发的事件做出反应。 如何对EventEmitter类的函数进行存根?
依赖类
const EventEmitter = require('events');
class FooBar extends EventEmitter {
constructor() {
super();
this.doingSomething = false;
}
doSomething() {
if (this.doingSomething === false) {
this.doingSomething = true;
this.emit('startedDoingSomething');
}
else {
this.emit('alreadyDoingSomething');
}
}
}
module.exports = FooBar;
被测模块
let Foobar = require('FooBar');
let fooBar = new FooBar();
exports.myFunction = () => {
// Set up listeners
fooBar.once('startedDoingSomething', () => {
fooBar.removeAllListeners();
// Some functionality
console.log('Started Doing Something');
});
fooBar.once('alreadyDoingSomething', () => {
fooBar.removeAllListeners();
// Some functionality
console.log('Already Doing Something');
});
// Call the event-emitting function
fooBar.doSomething();
};
// Other functions that use fooBar
我正在使用Sinon来创建存根,但是我无法对有效发出事件的类函数进行存根。 我根据[Feature request]存根发出的内容对测试进行了建模,但是由于被存根的事件发射器依赖项是一个类,因此不得不进行一些修改。
测试
let chai = require('chai');
let sinon = require('sinon');
let FooBar = require('FooBar');
let dependentModule = require('./dependentModule');
describe('Dependent Module', () => {
it('alreadyDoingSomething', () => {
sinon.stub(FooBar.prototype, 'pause', () => {
FooBar.prototype.emit('alreadyDoingSomething');
});
// Assertion statements here
expect(dependentModule.myFunction()).to...
});
});
即使正在调用存根函数,该方法实际上也不会发出事件。
测试中的第13行,它调用dependentModule.myFunction()
然后它跳到被测从属模块的第5行
然后在受测从属模块的第19行中,它调用fooBar.doSomething()
然后跳到Dependency Class中的第12行,那里this.doingSomething
为false,因此它发出了startedDoingSomething
。
然后,它跳到“受测模块”中的第7行,它调用fooBar.removeAllListeners();
,这意味着在同一文件的第34行注册的事件处理程序也将被删除。
这是真的吗?
现在,假设第7行“受测模块”中的fooBar.removeAllListeners
已被注释掉。
然后在Test的第13行之后,它调用FooBar.prototype.pause
,然后依次调用FooBar.prototype.emit('alreadyDoingSomething');
问题在于,当FooBar.prototype.emit
时, this
在上下文中不等于在受测模块中的第2行中声明的fooBar
。 (等于FooBar.prototype
)
所以FooBar.prototype.emit('alreadyDoingSomething');
不会触发在受测模块中第12行中定义的事件处理程序。
我们将需要找到一种方法来调用fooBar.emit('alreadyDoingSomething')
。
但这是不可能的,因为除非使用诸如rewire之类的库,否则永远不会导出fooBar
。
现在假设我们添加了exports.fooBar = fooBar;
到被测相关模块的末尾。
并且我们还将Test中的第9行更改为this.emit('alreadyDoingSomething')
这很重要,因为我们需要在调用this.emit('alreadyDoingSomething')
时需要上下文作为实例,在我们的例子中是fooBar
。
现在在测试中,当调用dependentModule.fooBar.pause()
时,将触发一个“已经开始做事”。
现在,您应该在控制台中看到Already Doing Something
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.