- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
如何测试事件监听器的回调函数是否被调用?例如,我有以下代码,其中 app.js 通过 init.js Controller 初始化应用程序。
main.js 文件有一个类扩展和事件发射器,使对象成为事件发射器。
app.js
const initController = require('./init');
async function init() {
initController.startMain();
}
init();
main.js
const events = require('events'),
ui = require('./ui');
module.exports.getMain = function () {
class Main extends events.EventEmitter {
constructor() {
super();
this.status = null;
}
}
return new Main();
};
module.exports.init = () => {
const main = this.getMain();
ui.init(main);
this.start(main);
}
module.exports.start = (main) => {
ui.start(main);
main.emit('http-init');
main.emit('http-success');
main.emit('http-error');
};
ui.js
function init(main) {
main.on('http-init', onHttpInit.bind(this));
main.on('http-success', onHttpSuccess.bind(this));
main.on('http-error', onHttpError.bind(this));
main.once('app-ready', onAppReady.bind(this));
};
function start (main) {};
function onAppReady() {
console.log('APP READY');
};
function onHttpInit() {
console.log('HTTP INIT SEQUENCE');
};
function onHttpError(error) {
console.log('HTTP ERROR SEQUENCE');
};
function onHttpSuccess() {
console.log('HTTP SUCCESS SEQUENCE');
};
module.exports = exports = {
init,
start,
onHttpInit,
onHttpError,
onHttpSuccess,
};
init.js
exports.startMain = () => {
console.log('Start application');
// Load application modules
const main = require('./main');
// Start the application
main.init();
};
因此,当我运行命令 node app.js
时,我看到了以下输出
开始申请HTTP 初始化序列HTTP 成功序列HTTP 错误序列
这意味着监听器处于事件状态并且调用了函数。
ui.tests.js
const sinon = require('sinon'),
main = require('../main').getMain(),
proxyquire = require('proxyquire').noPreserveCache().noCallThru();
describe('UI Tests', () => {
const sandbox = sinon.createSandbox();
let controller = null;
before(() => {
controller = proxyquire('../ui', {});
})
describe('Testing Eventlisteners', ()=> {
afterEach(() => {
main.removeAllListeners();
});
const eventMap = new Map([
[ 'http-init', 'onHttpInit' ],
[ 'http-success', 'onHttpSuccess' ],
[ 'http-error', 'onHttpError']
]);
eventMap.forEach((value, key) => {
it(`should register an eventlistener on '${key}' to ${value}`, () => {
const stub = sinon.stub(controller, value);
controller.init(main);
main.emit(key);
sinon.assert.called(stub);
})
})
})
})
然而,当我运行上面的测试时,即使我得到了输出,即调用了函数,但是,sinon assert 总是失败,说下面的内容:
UI Tests
Testing Eventlisteners
HTTP INIT SEQUENCE
1) should register an eventlistener on 'http-init' to onHttpInit
HTTP SUCCESS SEQUENCE
2) should register an eventlistener on 'http-success' to onHttpSuccess
HTTP ERROR SEQUENCE
3) should register an eventlistener on 'http-error' to onHttpError
0 passing (16ms)
3 failing
1) UI Tests
Testing Eventlisteners
should register an eventlistener on 'http-init' to onHttpInit:
AssertError: expected onHttpInit to have been called at least once but was never called
at Object.fail (node_modules/sinon/lib/sinon/assert.js:106:21)
at failAssertion (node_modules/sinon/lib/sinon/assert.js:65:16)
at Object.assert.(anonymous function) [as called] (node_modules/sinon/lib/sinon/assert.js:91:13)
at Context.it (test/ui.tests.js:25:30)
2) UI Tests
Testing Eventlisteners
should register an eventlistener on 'http-success' to onHttpSuccess:
AssertError: expected onHttpSuccess to have been called at least once but was never called
at Object.fail (node_modules/sinon/lib/sinon/assert.js:106:21)
at failAssertion (node_modules/sinon/lib/sinon/assert.js:65:16)
at Object.assert.(anonymous function) [as called] (node_modules/sinon/lib/sinon/assert.js:91:13)
at Context.it (test/ui.tests.js:25:30)
3) UI Tests
Testing Eventlisteners
should register an eventlistener on 'http-error' to onHttpError:
AssertError: expected onHttpError to have been called at least once but was never called
at Object.fail (node_modules/sinon/lib/sinon/assert.js:106:21)
at failAssertion (node_modules/sinon/lib/sinon/assert.js:65:16)
at Object.assert.(anonymous function) [as called] (node_modules/sinon/lib/sinon/assert.js:91:13)
at Context.it (test/ui.tests.js:25:30)
我不知道为什么即使该函数至少被调用一次,测试也会失败,这可以从输出 HTTP INIT SEQUENCE
、HTTP SUCCESS SEQUENCE
和 HTTP 错误序列
当我运行测试时。
我试着做 stub.should.have.been.called;
。有了这个测试通过,但是,它并没有真正通过 stub.should.have.been.called;
或 stub.should.not.have.been.called;
不管怎样都通过测试,而不是后者未通过测试。
有人知道这个测试失败的原因吗?感谢您的帮助。
最佳答案
您运行 const stub = sinon.stub(controller, value);
来 stub 由您的 ui
模块导出的值。这确实改变了模块导出的值,但问题出在 ui
模块中的这段代码:
function init(main) {
main.on('http-init', onHttpInit.bind(this));
main.on('http-success', onHttpSuccess.bind(this));
main.on('http-error', onHttpError.bind(this));
main.once('app-ready', onAppReady.bind(this));
}
从这段代码的 Angular 来看,module.exports
是被你的调用sinon.stub(controller, value)
改变了,但是这不会更改上面代码中符号 onHttpInit
、onHttpSuccess
等符号的值,因为这些符号是 ui 范围内的局部符号
模块。您可以随心所欲地改变 module.exports
:它仍然对上面的代码没有影响。
您可以将代码更改为:
function init(main) {
main.on('http-init', exports.onHttpInit.bind(this));
main.on('http-success', exports.onHttpSuccess.bind(this));
main.on('http-error', exports.onHttpError.bind(this));
main.once('app-ready', exports.onAppReady.bind(this));
}
您可以直接使用 exports
,因为您为 module.exports
和 exports
分配了相同的值,其中 module.exports =导出 = ...
此更改应该可以解决您遇到的直接问题。但是,我会在这里修改测试方法。您的测试标题为 should register an eventlistener on '${key}' to ${value}
但实际上您正在测试的不仅仅是事件监听器已注册,而且事件传播有效。实际上,您正在测试 EventEmitter
负责提供的功能。我将更改测试以对 main
对象的 on
方法进行 stub ,并验证是否已使用适当的值调用它。然后测试将测试它实际宣传的内容。
关于javascript - Node : How to assert if event callback function was called using sinon,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57657332/
我是一名优秀的程序员,十分优秀!