Stub 一个 ES6 EventEmitter class 函数
Stub a ES6 EventEmitter class function
我有一个扩展 EventEmitter 的依赖项 class,我需要测试使用此依赖项的函数如何根据它触发的事件做出反应。如何存根 EventEmitter 的函数 class?
依赖关系Class
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 来创建一个存根,但我无法对 class 有效发出事件的函数进行存根。我根据 [Feature request] stub emits 对我的测试进行了建模,但不得不进行一些修改,因为被存根的事件发射器依赖项是 class.
测试
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()
然后跳转到Dependent Module Under Test中的第5行
然后在 Dependent Module Under Test 的第 19 行,它调用 fooBar.doSomething()
然后它跳转到 Dependency Class 中的第 12 行,那里 this.doingSomething
是 false,所以它发出 startedDoingSomething
.
然后跳转到Dependent Module Under Test中的第7行,调用fooBar.removeAllListeners();
,也就是说同一个文件第34行注册的事件处理器也被移除
这是真的吗?
现在假设第 7 行中的 fooBar.removeAllListeners
Dependent Module Under Test 被注释掉了。
在测试的第 13 行之后,它调用 FooBar.prototype.pause
,后者又调用 FooBar.prototype.emit('alreadyDoingSomething');
问题是调用FooBar.prototype.emit
时,context中的this
不等于Dependent Module Under Test中第2行声明的fooBar
。 (等于FooBar.prototype
)
因此FooBar.prototype.emit('alreadyDoingSomething');
不会触发在Dependent Module Under Test中第12行定义的事件处理程序。
我们需要找到一种方法来调用 fooBar.emit('alreadyDoingSomething')
。
但这是不可能的,因为 fooBar
永远不会导出,除非使用像 rewire 这样的库。
现在假设我们将 exports.fooBar = fooBar;
添加到 Dependent Module Under Test 的末尾。
并且我们还将Test中的第9行更改为this.emit('alreadyDoingSomething')
这很重要,因为我们需要调用emit时的上下文需要是实例,在我们的例子中是fooBar
.
现在在测试中,当调用 dependentModule.fooBar.pause()
时,会触发 alreadyDoingSomething。
现在您应该会在控制台中看到 Already Doing Something
。
我有一个扩展 EventEmitter 的依赖项 class,我需要测试使用此依赖项的函数如何根据它触发的事件做出反应。如何存根 EventEmitter 的函数 class?
依赖关系Class
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 来创建一个存根,但我无法对 class 有效发出事件的函数进行存根。我根据 [Feature request] stub emits 对我的测试进行了建模,但不得不进行一些修改,因为被存根的事件发射器依赖项是 class.
测试
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()
然后跳转到Dependent Module Under Test中的第5行
然后在 Dependent Module Under Test 的第 19 行,它调用 fooBar.doSomething()
然后它跳转到 Dependency Class 中的第 12 行,那里 this.doingSomething
是 false,所以它发出 startedDoingSomething
.
然后跳转到Dependent Module Under Test中的第7行,调用fooBar.removeAllListeners();
,也就是说同一个文件第34行注册的事件处理器也被移除
这是真的吗?
现在假设第 7 行中的 fooBar.removeAllListeners
Dependent Module Under Test 被注释掉了。
在测试的第 13 行之后,它调用 FooBar.prototype.pause
,后者又调用 FooBar.prototype.emit('alreadyDoingSomething');
问题是调用FooBar.prototype.emit
时,context中的this
不等于Dependent Module Under Test中第2行声明的fooBar
。 (等于FooBar.prototype
)
因此FooBar.prototype.emit('alreadyDoingSomething');
不会触发在Dependent Module Under Test中第12行定义的事件处理程序。
我们需要找到一种方法来调用 fooBar.emit('alreadyDoingSomething')
。
但这是不可能的,因为 fooBar
永远不会导出,除非使用像 rewire 这样的库。
现在假设我们将 exports.fooBar = fooBar;
添加到 Dependent Module Under Test 的末尾。
并且我们还将Test中的第9行更改为this.emit('alreadyDoingSomething')
这很重要,因为我们需要调用emit时的上下文需要是实例,在我们的例子中是fooBar
.
现在在测试中,当调用 dependentModule.fooBar.pause()
时,会触发 alreadyDoingSomething。
现在您应该会在控制台中看到 Already Doing Something
。