Catch 'uncaughtException' error in your mocha test
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'
UPDATE: The links in the article might be broken.