我如何testing摩卡未被捕获的错误?

我想testing下面的函数按预期执行:

function throwNextTick(error) { process.nextTick(function () { throw error; }); } 

这是我的尝试:

 describe("throwNextTick", function () { it("works as expected", function (next) { var error = new Error("boo!"); var recordedError = null; process.once("uncaughtException", function (error) { recordedError = error; }); throwNextTick(error); process.nextTick(function () { recordedError.should.be(error); next(); }); }); }); 

但摩卡似乎想保留任何错误本身,并得到它们时,我的testing失败:

 C:\Users\ddenicola\Programming (Synced)\pubit>mocha test/basicTest.js throwNextTick 0) works as expected ? 1 of 1 tests failed: 1) throwNextTick works as expected: Error: boo! at Test.fn (C:\Users\ddenicola\Programming (Synced)\pubit\test\basicTest.js:11:21) at Test.run (C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runnable.js:144:15) at Runner.runTest (C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:271:10) at C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:315:12 at next (C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:199:14) at C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:208:7 at next (C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:157:23) at Array.0 (C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:176:5) at EventEmitter._tickCallback (node.js:192:40) 

有任何想法吗?

更新:感谢casey-foster在下面的评论:

从节点v6.0.0开始,可以使用process.prependOnceListener('uncaughtException', ...)来更简洁地完成此操作。


老答案:

秘密在于process.listeners('uncaughtException'):

http://nodejs.org/docs/latest/api/events.html#emitter.listeners

只需删除摩卡侦听器,添加自己的,然后重新附加摩卡侦听器。

见下文:

 var assert = require('assert') function throwNextTick(error) { process.nextTick(function () { throw error }) } describe("throwNextTick", function () { it("works as expected", function (next) { var error = new Error("boo!") var recordedError = null var originalException = process.listeners('uncaughtException').pop() //Needed in node 0.10.5+ process.removeListener('uncaughtException', originalException); process.once("uncaughtException", function (error) { recordedError = error }) throwNextTick(error); process.nextTick(function () { process.listeners('uncaughtException').push(originalException) assert.equal(recordedError, error) next() }) }) }) 

如果你的asynchronous代码是在一个域内执行的 – 而且往往是这种情况 – 你需要更改域上的错误监听器而不是进程。

为此,您可以使用:

 it('should produce an unhandled exception', function (done) { // Remove Mocha's error listener var originalErrorListeners = process.domain.listeners('error'); process.domain.removeAllListeners('error'); // Add your own error listener to check for unhandled exceptions process.domain.on('error', function () { // Add the original error listeners again process.domain.removeAllListeners('error'); for ( var i = 0; i < originalErrorListeners.length; i+=1 ) { process.domain.on('error', originalErrorListeners[i]); } // For the sake of simplicity we are done after catching the unhandled exception done(); }); // This would be your async application code you expect to throw an exception setTimeout(function () { throw new Error(); }); }); 

基于Timoxley&Casey Foster,在节点v6 ++中

 const assert = require('assert') describe('throwNextTick', function() { it('works as expected', function(next) { function cb(err) { assert.equal(err instanceof Error, true) next() } function test(){ process.nextTick(() => { throw new Error('err') }) } process.prependOnceListener('uncaughtException', cb) test() }) })