Mocha website states:
"To make things even easier, the done() callback accepts an error, so we may use this directly: [see their example]"
So lets try that:
it('works',function(done){
expect(1).to.be(1)
done( new Error('expected error') )
})
/* Insert the error manually for testing and clarity. */
run it and:
1 failing
1) works:
Error: expected error
at Context.<anonymous>
[stack trace]
How do we make the test pass when the error response is the desired result?
Error thrown from async function is a rejected promise (1) Use . catch() chain function to catch the error within the promise chain. (2) Change testFn to an async function and use await to wait for the resolution of the rejected promise.
Return a promise from your test, and Jest will wait for that promise to resolve. If the promise is rejected, the test will fail.
You can cancel an asynchronous operation after a period of time by using the CancellationTokenSource. CancelAfter method if you don't want to wait for the operation to finish.
expect(value) The expect function is used every time you want to test a value. You will rarely call expect by itself. Instead, you will use expect along with a "matcher" function to assert something about a value.
That's not async. The callback function is just there for you to inform mocha that you're testing async code and so mocha shouldn't run the next test until you call the callback function. This is an example of how to use the callback function:
it('works',function(done){
setTimeout(function(){
// happens 0.5 seconds later:
expect(1).to.be(1);
done(); // this tells mocha to run the next test
},500);
});
Also, mocha does not handle any form of exceptions, async or otherwise. It leaves that up to an exception library of your choosing. In your case you're using expect.js
? If so, expect handles expected errors via the throwException
method (also called throwError
):
it('throws an error',function(done){
expect(function(){
throw new Error('expected error');
}).to.throwError(/expected error/);
});
Now, in general async code in node.js don't throw errors. They pass errors to the callback as parameters instead. So to handle async errors you can simply check the err object:
// using readFile as an example of async code to be tested:
it('returns an error',function(done){
fs.readFile(filename, function (err, data) {
expect(err).to.be.an(Error);
done(); // tell mocha to run next test
})
});
So use to.throwError()
if you're checking synchronous errors and to.be.an(Error)
if you're checking async errors.
The first time I saw this I was stumped. How can mocha know that the test is synchronous or asynchronous when the only difference is weather the function you pass to it accepts an argument or not? In case you're like me and are scratching your head wondering how, I learned that all functions in javascript have a length
property that describes how many arguments it accepts in its declaration. No, not the arguments.length
thing, the function's own length
. For example:
function howManyArguments (fn) {
console.log(fn.length);
}
function a () {}
function b (x) {}
function c (x,y,z) {}
howManyArguments(a); // logs 0
howManyArguments(b); // logs 1
howManyArguments(c); // logs 3
howManyArguments(howManyArguments); // logs 1
howManyArguments(function(x,y){}); // logs 2
So mocha basically checks the function's length to determine weather to treat it as a synchronous function or asynchronous function and pauses execution waiting for the done()
callback if it's asynchronous.
Mocha, like most other js unit test runners and libraries, work by catching errors. So it expects functions like expect(foo).to.be.an.integer()
to throw an error if the assertion fails. That's how mocha communicates with assertion libraries like expect or chai.
Now, as I mentioned above, a common idiom in node is that async functions don't throw errors but passes an error object as the first argument. When this happens mocha cannot detect the error and so can't detect a failing test. The work-around to this is that if you pass the error object from the async code to the callback function it will treat it the same as a thrown error.
So, taking one of my examples above:
it('executes without errors',function(done){
fs.readFile(filename, function (err, data) {
done(err); // if err is undefined or null mocha will treat
// it as a pass but if err is an error object
// mocha treats it as a fail.
})
});
Or simply:
it('executes without errors',function(done){
fs.readFile(filename,done);
});
Strictly speaking, this feature is a bit redundant when used with libraries like expect.js which allows you to manually check the returned error object but it's useful for when your assertion library can't check the error object (or when you don't really care about the result of the async function but just want to know that no errors are thrown).
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