Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to get Chai working with asynchronous Mocha tests?

I'm running some asynchronous tests in Mocha using the Browser Runner and I'm trying to use Chai's expect style assertions:

window.expect = chai.expect; describe('my test', function() {   it('should do something', function (done) {     setTimeout(function () {       expect(true).to.equal(false);     }, 100);   } } 

This doesn't give me the normal failed assertion message, instead I get:

Error: the string "Uncaught AssertionError: expected true to equal false" was thrown, throw an Error :)     at Runner.fail (http://localhost:8000/tests/integration/mocha/vendor/mocha.js:3475:11)     at Runner.uncaught (http://localhost:8000/tests/integration/mocha/vendor/mocha.js:3748:8)     at uncaught (http://localhost:8000/tests/integration/mocha/vendor/mocha.js:3778:10) 

So it's obviously catching the error, it's just not displaying it correctly. Any ideas how to do this? I guess I could just call "done" with an error object but then I lose all the elegance of something like Chai and it becomes very clunky...

like image 389
Thomas Parslow Avatar asked Jun 27 '12 22:06

Thomas Parslow


People also ask

How do you test async function in Mocha chai?

Writing Asynchronous Tests with Mocha. To indicate that a test is asynchronous in Mocha, you simply pass a callback as the first argument to the it() method: it('should be asynchronous', function(done) { setTimeout(function() { done(); }, 500); });

Is Mocha BDD?

With its default “BDD”-style interface, Mocha provides the hooks before() , after() , beforeEach() , and afterEach() . These should be used to set up preconditions and clean up after your tests.

What is Mocha and chai?

Mocha is a JavaScript test framework running on Node. js and in the browser. Mocha allows asynchronous testing, test coverage reports, and use of any assertion library. Chai is a BDD / TDD assertion library for NodeJS and the browser that can be delightfully paired with any javascript testing framework.

What is Mocha unit test?

Mocha is a widely used JavaScript test framework running on NodeJS and browsers. It supports asynchronous testing running the tests serially, allowing for more flexible and accurate reporting. It is a highly customizable framework that supports different assertions and libraries.


1 Answers

Your asynchronous test generates an exception, on failed expect()ations, that cannot be captured by it() because the exception is thrown outside of it()'s scope.

The captured exception that you see displayed is captured using process.on('uncaughtException') under node or using window.onerror() in the browser.

To fix this issue, you need to capture the exception within the asynchronous function called by setTimeout() in order to call done() with the exception as the first parameter. You also need to call done() with no parameter to indicate success, otherwise mocha would report a timeout error because your test function would never have signaled that it was done:

window.expect = chai.expect;  describe( 'my test', function() {   it( 'should do something', function ( done ) {     // done() is provided by it() to indicate asynchronous completion     // call done() with no parameter to indicate that it() is done() and successful     // or with an error to indicate that it() failed     setTimeout( function () {       // Called from the event loop, not it()       // So only the event loop could capture uncaught exceptions from here       try {         expect( true ).to.equal( false );         done(); // success: call done with no parameter to indicate that it() is done()       } catch( e ) {         done( e ); // failure: call done with an error Object to indicate that it() failed       }     }, 100 );     // returns immediately after setting timeout     // so it() can no longer catch exception happening asynchronously   } } 

Doing so on all your test cases is annoying and not DRY so you might want to provide a function to do this for you. Let's call this function check():

function check( done, f ) {   try {     f();     done();   } catch( e ) {     done( e );   } } 

With check() you can now rewrite your asynchronous tests as follows:

window.expect = chai.expect;  describe( 'my test', function() {   it( 'should do something', function( done ) {     setTimeout( function () {       check( done, function() {         expect( true ).to.equal( false );       } );     }, 100 );   } } 
like image 93
Jean Vincent Avatar answered Oct 17 '22 12:10

Jean Vincent