Node.js How To Get Better Error Messages For Async Tests Using Mocha
Solution 1:
When you get a timeout error rather than a more precise error, the first thing to do is to check that your code does not swallow exceptions, and that it does not swallow promise rejections. Mocha is designed to detect these in your tests. Unless you do something unusual like running test code in your own VM or manipulate domains, Mocha will detect such failures, but if your code swallows them, there's nothing Mocha can do.
This being said, Mocha won't be able to tell you that done
was not called because your implementation has a logic bug that causes it to fail to call the callback.
Here is what could be done with sinon
to perform a post mortem after test failures. Let me stress that this is a proof of concept. If I wanted to use this on an ongoing basis, I'd develop a proper library.
var sinon = require("sinon");
var assert = require("assert");
// MyEmitter is just some code to test, created for the purpose of// illustration.varMyEmitter = require("./MyEmitter");
var emitter = newMyEmitter();
var postMortem;
beforeEach(function () {
postMortem = {
calledOnce: []
};
});
afterEach(function () {
// We perform the post mortem only if the test failed to run properly.if (this.currentTest.state === "failed") {
postMortem.calledOnce.forEach(function (fn) {
if (!fn.calledOnce) {
// I'm not raising an exception here because it would cause further// tests to be skipped by Mocha. Raising an exception in a hook is// interpreted as "the test suite is broken" rather than "a test// failed".console.log("was not called once");
}
});
}
});
it("client should do something", function(done) {
var doneFn = function(args) {
// If you change this to false Mocha will give you a useful error. This is// *not* due to the use of sinon. It is wholly due to the fact that// `MyEmitter` does not swallow exceptions.assert(true);
done();
};
// We create and register our spy so that we can conduct a post mortem if the// test fails.var spy = sinon.spy(doneFn);
postMortem.calledOnce.push(spy);
emitter.on("foo", spy);
emitter.triggerEvent("foo");
});
Here is the code of MyEmitter.js
:
varEventEmitter = require("events");
functionMyEmitter() {
EventEmitter.call(this);
}
MyEmitter.prototype = Object.create(EventEmitter.prototype);
MyEmitter.prototype.constructor = MyEmitter;
MyEmitter.prototype.triggerEvent = function (event) {
setTimeout(this.emit.bind(this, event), 1000);
};
module.exports = MyEmitter;
Solution 2:
You should to listen to uncaughtException
events, in addition to someEvent
. This way you'll catch errors happening in client, and those will show up in your test report.
it("; client should do something", function(done) {
var doneFn = function(args) {
// run a bunch of asserts on args
client.events.removeListener(client.events.someEvent, userMuteFn);
done();
}
var failedFn = function(err) {
client.events.removeListener('uncaughtException', failedFn);
// propagate client errordone(err);
}
client.events.on(someEvent, doneFn);
client.events.on('uncaughtException', failedFn);
client.triggerEvent();
});
P.S. In case client
is a child process, you also should listen to exit
event, which will be triggered in case the child process dies.
Post a Comment for "Node.js How To Get Better Error Messages For Async Tests Using Mocha"