It is not asynchronous. The callback function is designed to tell mocha that you are testing asynchronous code, and therefore mocha should not run the next test until you call the callback function. This is an example of using a callback function:
it('works',function(done){ setTimeout(function(){
In addition, mocha does not handle any exceptions, asynchronous or others. It leaves this exception library of your choice. In your case, are you using expect.js ? If so, expect to handle the expected errors with 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, asynchronous code in node.js does not throw errors. Instead, they pass errors to the callback. Therefore, to handle asynchronous 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 are checking for synchronous errors and to.be.an(Error) if you are checking for asynchronous errors.
Additional notes:
The first time I saw this, I was at a standstill. How can mocha know that a test is synchronous or asynchronous when the only difference is that the function you pass to it accepts an argument or not? In case you look like me and scratch your head, wondering how, I found out that all functions in javascript have a length property that describes how many arguments it takes in its declaration. No, not arguments.length thing, own length function. For example:
function howManyArguments (fn) { console.log(fn.length); } function a () {} function b (x) {} function c (x,y,z) {} howManyArguments(a);
Thus, mocha basically checks the length of the function to determine the weather, to treat it as a synchronous function or an asynchronous function, and pauses execution, waiting for a done() callback if it is asynchronous.
More notes:
Mocha, like most other js unit test runners and libraries, works by catching errors. Therefore, he expects functions like expect(foo).to.be.an.integer() error if the statement fails. This is how mocha interacts with statement libraries like expect or chai.
Now, as I mentioned above, the general idiom in node is that asynchronous functions do not throw errors, but pass the error object as the first argument. When this happens, mocha cannot detect the error and therefore cannot detect the failed test. A workaround for this is that if you pass the error object from the asynchronous code to the callback function, it will handle it the same way as the flushed error.
So, taking one of my examples above:
it('executes without errors',function(done){ fs.readFile(filename, function (err, data) { done(err);
Or simply:
it('executes without errors',function(done){ fs.readFile(filename,done); });
Strictly speaking, this function is a little redundant when used with libraries like expect.js, which allows you to manually check the returned error object, but it is useful when your claims library cannot check the error object (or when you really don't care about the result of the function async, but just want to know that there were no errors.)