Catch 'uncaughtException' error in your mocha test
By David WORMS
Oct 27, 2013
- Categories
- Node.js
- Tags
- DevOps
- Mocha
- JavaScript
- Unit tests
Never miss our publications about Open Source, big data and distributed systems, low frequency of one email every two months.
This isn’t the first time I faced this situation. Today, I finally found the time and energy to look for a solution. In your mocha test, let’s say you need to test an expected “uncaughtException” event, the Node.js technique to catch the uncatchable. Easy, just register an “uncaughtException” listener to the process event emitter. Well, not so easy, but not so complicate either.
Let’s start with a simple test:
describe 'uncaughtException', ->
it 'should be tested', (next) ->
try
process.nextTick ->
idontexist()
catch e
console.error 'Never called'
Install mocha with npm install mocha
, save the file as ‘test.coffee’ and run mocha --compilers coffee:coffee-script test.coffee
. As you can see, the error isn’t caught by your code, only mocha get a hold of it.
So the obvious starting point is to register an “uncaughtException” event listener, part of the native Node.js “process” module. That gives us:
describe 'uncaughtException', ->
it 'should be tested', (next) ->
process.on 'uncaughtException', (err) ->
console.error 'idontexist is not defined'
next()
try
process.nextTick ->
idontexist()
catch e
console.error 'Never called'
As you can notice, we are grabbing the error and we are able to call the “next” callback. However, Mocha gets into our legs and does not let us handle that error gracefully. It reports that error as an error, even if we were happy about it. What an intrusive behavior, but let’s not blame Mocha, it is required for other situations.
What can we do about it? We unplug the mocha listener, and any other listener if there are any, plug ours and, when we’re done, re-wire everything the way it was, not forgetting to unplug our just created listener. Hope I was clear. This is the final code:
describe 'uncaughtException', ->
it 'should be tested', (next) ->
lsts = process.listeners 'uncaughtException'
process.removeAllListeners 'uncaughtException'
process.on 'uncaughtException', (err) ->
console.error 'idontexist is not defined'
process.removeAllListeners 'uncaughtException'
for lst in lsts
process.on 'uncaughtException', lst
next()
try
process.nextTick ->
idontexist()
catch e
console.error 'Never called'
You can view it in action in the just published error test part of the each iterator module.
UPDATE: The links in the article might be broken.