Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocha/Chai async tests 'done()' fn not working

I'm testing a bank model I have as follows:

describe('Bank Model - Ajax', function () {

    it('loads bank', function (done) {

        var bank = new Bank();

        bank.OnLoaded = _(function () {
            expect(this.id).to.eql(1171);
            expect(true).to.eql(false);
            done();
        }).bind(bank);

        bank.load(1171);


    });
});

The load call makes an ajax request to my server. My problem is that expect(true).to.eql(false); throws an Uncaught Assertion Error and I'm not sure why. I'm using the recommended Mocha strategy of ending my test case with a done. Am I doing it wrong?

Thanks.

like image 773
khalid13 Avatar asked Nov 11 '13 20:11

khalid13


People also ask

How do you test async function in Chai?

we practically combine all the solution ( async/await , promise based and callback done ) for async test in the test file. Let's use the recent solution using async/await so it will be: describe('testing users ', () => { it('can get all users', async () => { const response = await chai.

How do I run a single test file in Mocha?

Learn how to run only one test with Mocha To run a single test (as defined in it() ), you can simply call the only() method on it in the following way: it. only('...', function () { // only this test will run... });

Does Mocha run tests in parallel?

Mocha does not run individual tests in parallel. That means if you hand Mocha a single, lonely test file, it will spawn a single worker process, and that worker process will run the file. If you only have one test file, you'll be penalized for using parallel mode. Don't do that.


1 Answers

You're not doing anything wrong. Mocha isn't easily able to catch exceptions that are thrown within a callback since they execute after the test function has finished, so any failed assertions are uncaught fatal errors instead of nice diffs that you normally get with synchronous code.

People are working on workarounds such as providing a custom method that assertion libraries can call instead of throwing, or using Node Domains when running in Node. But for now it seems that it is still not behaving ideally.

Since the done method accepts a single parameter containing an error, you can add code to your test to catch exceptions within the callback and pass them to done(err) inside the catch block. But it'd get pretty messy fast.

Could reduce repetition with some sort of helper function like the below:

function catching(done, fn) {
  try {
    fn();
    done();
  } catch(err) {
    done(err);
  }
}

And then:

bank.OnLoaded = catching(done, _(function () {
  expect(this.id).to.eql(1171);
  expect(true).to.eql(false);
}).bind(bank));
like image 104
Nick Avatar answered Oct 06 '22 00:10

Nick