2012-01-26 41 views
12

我想測試下按預期執行:如何測試摩卡未被捕獲的錯誤?

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

但摩卡似乎想保留任何錯誤本身,並不能在我的測試當它得到他們:

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) 

任何想法?

回答

27

更新:凱西福斯特的禮貌在下面留言:

爲節點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() 
     }) 
    }) 
}) 
+1

這並獲得成功!我只會對你的回答做一個編輯:你需要在執行assert之前恢復原始的監聽器,因爲assert會拋出一個錯誤。 – Domenic

+0

這確實應該在Mocha的文檔中!我用了一個小時的谷歌搜索來找到這個答案。如果你沒有拋出一個標準的錯誤對象(根據克羅克福德的建議),摩卡沒有記錄的錯誤捕獲(以及失敗的測試),以及沒有顯示錯誤信息的事實,使得真的很難弄清爲什麼測試失敗。 –

+7

看來,在最新版本的節點(本評論時爲v0.10.5)'process.listeners(eventName)'返回監聽器數組的副本,所以調用'pop()'實際上並不會從發射器中移除聽衆。你需要在pop之後添加以下行:'process.removeListener('uncaughtException',originalException);' –

0

如果您的異步代碼是域內執行- 這是常有的事 - 你需要更改域,而不是過程中的錯誤監聽。

對於您可以使用:

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

}); 
-1

基礎上timoxley &凱西福斯特,在節點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() 

    }) 
}) 
+0

此語法('import')在Node.js中不起作用。 – Domenic

+0

你可以用'''''''''''''''''''''' - '''''''''''''''''''''''''''''''' - '' 「]}''' – syarul

相關問題