How to pass a test with expect.js async done () with an error?

The Mocha website says:

"To make things even easier, the done () callback accepts the error, so we can use it directly: [see their example]"

So try the following:

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 to make a test pass when the answer to the error is the desired result?

+7
javascript
source share
2 answers

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(){ // happens 0.5 seconds later: expect(1).to.be(1); done(); // this tells mocha to run the next test },500); }); 

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); // logs 0 howManyArguments(b); // logs 1 howManyArguments(c); // logs 3 howManyArguments(howManyArguments); // logs 1 howManyArguments(function(x,y){}); // logs 2 

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); // 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 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.)

+19
source share

You can also return your asynchronous program, such as a promise, as shown below.

 it('Test DNA', () => { return resolvedPromise.then( (result)=>{ expect(result).to.equal('He is not a your father.'); },(err)=>{ console.log(err); }); }); 
0
source share

All Articles