Can I make Chai's expect.to.not.throw synchronous?

778 views Asked by At

I have a snippet of code that I'm testing in Chai and Pact. It looks something like this:

var myVerify = () => {
  provider.verify().then(() => {
    console.log('B verified')
    done()
  })
}
expect(myVerify).to.not.throw()

This works but it's a lot of extra work to go through to make a wrapper function to ensure that I wait on Pact's verify complete's before continuing on with the test. Pact has some internal state that will clear when it's done. If I just call this:

expect(provider.verify()).to.not.throw()

then it will conflict with other tests.

This code seems to work fine for me but it's very messy. Is there a simpler way to accomplish this?

1

There are 1 answers

3
J_A_X On

I wouldn't recommend this method since if an error did in fact occur, it would never be caught anyways because promises don't "throw errors", they simply reject the promise, which you can catch using .catch or being the second parameter of the .then.

There are 2 ways of doing what you want:

  1. Just with Mocha:

    return provider.verify().then(() => {
          console.log('B verified');
          done();
    }, () => throw new Error("B verification failed"));
    

    In this simple example, we're not using chai to verify anything since you're not actually verifying data output of the verify, you're just checking to see if the promise was a success, if not, throw an error which will fail your tests. Mocha, by default, understands promises as long as they're returned as part of the test.

    However, this method means that the wrapping it function needs to inject the done parameter, which I'm not a fan of. What I am a fan of is using:

  2. Chai with Chai as Promised:

    You need to set up Chai as Promised using

    chai.use(require("chai-as-promised))
    

    then in your tests, simply do:

    return expect(provider.verify()).to.eventually.be.fulfilled;
    

    This test will wait for the promise to return, and chai will validate that it is, in fact, fulfilled and not rejected. I find this syntax to be much simpler to use and makes writing tests simpler. You can also have multiple expects with the same promise, using Promises.all:

    var verify = provider.verify();
    return Promises.all(
        expect(verify).to.eventually.be.fulfilled,
        expect(verify).to.eventually.be.true,
    );