[英]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.