事件没有捕获我的testing与残桩function

我遇到了一个我不明白的问题。 我发出的事件在我的testing中没有被捕获。 这是下面的代码( 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; 

而相应的testing:

 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'); 发生
  • execfunction实际上是由于console.log(cmd); 发生

但是testing失败,出现这个错误消息:

 ~ % 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) 

如果我从testing中删除存根,testing运行正常。 如果我增加超时,我仍然有同样的问题。

任何想法我做错了什么?

问候

您的存根(stub)更改了process.exec()的同步/asynchronous方面。

内部Node的实现保证callback总是在事件循环的下一个回合中运行:

 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 

您的存根会立即调用callback:

 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(); }); 

解决scheme是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); }); }; 

你的testing还有另外一个问题:执行存根callback中的_self指的是全局对象,你将值保存到global.cmd 。 您期望在exec.cmd的testing中具有exec.cmd中的值。

这是execStub的最终和固定版本:

 var execStub = function() { var _self = sinon.stub(proc, 'exec', function(cmd, callback) { _self.cmd = cmd; console.log(cmd); process.nextTick(callback); }); return _self; }; 

有关callbackasynchronous的更多信息,请参阅此文章 。