我遇到了一个我无法解决的问题。我发出的事件没有在我的测试中被捕获。
以下是代码(event.js
):
var util = require('util'),
proc = require('child_process'),
EventEmitter = require('events').EventEmitter;
var Event = function() {
var _self = this;
proc.exec('ls -l', function(error, stdout, stderr) {
_self.emit('test');
console.log('emitted');
});
};
util.inherits(Event, EventEmitter);
module.exports = Event;
相应的测试:
var proc = require('child_process'),
sinon = require('sinon'),
chai = require('chai'),
expect = chai.expect,
Event = require('./event'),
myEvent, exec;
var execStub = function() {
var _self = this;
return sinon.stub(proc, 'exec', function(cmd, callback) {
_self.cmd = cmd;
console.log(cmd);
callback();
});
};
describe('Event', function() {
beforeEach(function(){
exec = execStub();
});
afterEach(function(){
exec.restore();
});
it('Event should be fired', function(done) {
myEvent = new Event();
myEvent.on('test', function() {
expect(exec.cmd).to.equal('ls -l');
done();
});
});
});
现在,我看到的是:
console.log('emitted');
发生后的测试期间发出的exec
发生以来console.log(cmd);
函数实际上已存根但测试失败并超时,并显示错误消息:
~ % mocha --timeout 15000 -R spec event.test.js
Event
◦ Event should be fired: ls -l
emitted
1) Event should be fired
0 passing (15 seconds)
1 failing
1) Event Event should be fired:
Error: timeout of 15000ms exceeded
at null.<anonymous> (/usr/lib/node_modules/mocha/lib/runnable.js:165:14)
at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
如果我从测试中删除存根,测试运行正常。如果我增加超时,我仍然有同样的问题。
知道我做错了什么?
此致
答案 0 :(得分:2)
您的存根更改了process.exec()
的同步/异步方面。
内部Node的实现保证了回调总是在事件循环的下一轮中运行:
myEvent = new Event(); // calls process.exec
myEvent.on('test', function() {
expect(exec.cmd).to.equal('ls -l');
done();
});
// process.exec callback will be called after all this code is executed
您的存根正在立即调用回调:
myEvent = new Event(); // calls process.exec
// process.exec callback is called immediately
// test event is emitted before listeners are attached
myEvent.on('test', function() {
expect(exec.cmd).to.equal('ls -l');
done();
});
解决方案是process.nextTick()
:
var execStub = function() {
var _self = this;
return sinon.stub(proc, 'exec', function(cmd, callback) {
_self.cmd = cmd;
console.log(cmd);
process.nextTick(callback);
});
};
您的测试还有另一个问题:exec存根回调中的_self
指的是全局对象,您将值保存到global.cmd
。您希望以后在测试中使用exec.cmd
中的值。
这是最后的&amp;固定版execStub
:
var execStub = function() {
var _self = sinon.stub(proc, 'exec', function(cmd, callback) {
_self.cmd = cmd;
console.log(cmd);
process.nextTick(callback);
});
return _self;
};
有关回调异步性的更多信息,请参阅此post。