I am modifying a node.js library to support true asynchronous operations.
I am having troubles with Mocha and Chai to make this (a similar) test pass.
it('should throw an error', function() {
expect(function() {
process.nextTick(function() {
throw new Error('This is my error');
});
}).to.throw(Error);
});
The problem is - because of the nextTick - that the Error is thrown out of scope of it
and besides the test failing, Mocha also outputs the below.
Uncaught Error: This is my error
What is the proper way to structure this test in order to make it succeed?
Hmm... in a full-fledged application what I'd do is probably use something like Sinon to check that the method that should throw an error has been called and is throwing.
In code where you cannot do this, then the following method would trap the exception:
var expect = require("chai").expect;
var domain = require("domain");
it('should throw an error', function(done) {
var d = domain.create();
d.on('error', function (err) {
// Exit the current domain.
d.exit();
// We must execute this code at the next tick.
process.nextTick(function () {
console.log(err); // Just to show something on the console.
expect(err instanceof Error).to.be.true;
done();
});
});
d.run(function () {
process.nextTick(function() {
throw new Error('This is my error');
});
});
});
This code creates a "domain" stored in d
. A domain will emit error
events on uncaught exceptions that happen in it so we run the test inside the domain (d.run(...)
) we've created and wait for an exception to happen (d.on('error', ...
). We check that it is an Error
object. (In a real test, I'd also check the error message.) When we are finished we call done()
to tell Mocha that the asynchronous test is over.
The handler for error
events calls d.exit()
. This is to make it so that Mocha can catch the error normally if the assertion (expect(err instanceof Error)
...) turns out to fail. If we do not exit the domain, then the domain will trap the error. Also, the check itself must be performed on the next tick to be outside the d
domain.
domain
A Problem?NO!
The documentation for domain
comes with some warnings about shutting down operations once an uncaught exception is caught when running an ongoing process, like a server. Then the thing to do is to clean what can be cleaned and exit as soon as possible. However, using domain
in a test does not differ from what Mocha is already doing. The way Mocha catches unhandled exceptions in asynchronous code is by using process.on('uncaughtException'
. Upon catching an unhandled exception Mocha marks the current test as failed and continues. Yet the documentation regarding uncaughtException
says "Don't use it, use domains
instead. If you do use it, restart your application after every unhandled exception!"
Ergo, anyone who has a problem with using domain
should not be using Mocha in the first place.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With