Is there a way to get Chai working with asynchrono

2020-01-27 01:17发布

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...

13条回答
Melony?
2楼-- · 2020-01-27 01:17

If you like promised, try Chai as Promised + Q, which allow something like this:

doSomethingAsync().should.eventually.equal("foo").notify(done);
查看更多
贪生不怕死
3楼-- · 2020-01-27 01:21

Try chaiAsPromised! Aside from being excellently named, you can use statements like:

expect(asyncToResultingValue()).to.eventually.equal(true)

Can confirm, works very well for Mocha + Chai.

https://github.com/domenic/chai-as-promised

查看更多
We Are One
4楼-- · 2020-01-27 01:21

Based on this link provided by @richardforrester http://staxmanade.com/2015/11/testing-asyncronous-code-with-mochajs-and-es7-async-await/, describe can use a returned Promise if you omit the done parameter.

Only downside there has to be a Promise there, not any async function (you can wrap it with a Promise, thou). But in this case, code can be extremely reduced.

It takes into account failings from either in the initial funcThatReturnsAPromise function or the expectations:

it('should test Promises', function () { // <= done removed
    return testee.funcThatReturnsAPromise({'name': 'value'}) // <= return added
        .then(response => expect(response).to.have.property('ok', 1));
});
查看更多
倾城 Initia
5楼-- · 2020-01-27 01:24

Here are my passing tests for ES6/ES2015 promises and ES7/ES2016 async/await. Hope this provides a nice updated answer for anyone researching this topic:

import { expect } from 'chai'

describe('Mocha', () => {
  it('works synchronously', () => {
    expect(true).to.equal(true)
  })

  it('works ansyncronously', done => {
    setTimeout(() => {
      expect(true).to.equal(true)
      done()
    }, 4)
  })

  it('throws errors synchronously', () => {
    return true
    throw new Error('it works')
  })

  it('throws errors ansyncronously', done => {
    setTimeout(() => {
      return done()
      done(new Error('it works'))
    }, 4)
  })

  it('uses promises', () => {
    var testPromise = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('Hello')
      }, 4)
    })

    testPromise.then(result => {
      expect(result).to.equal('Hello')
    }, reason => {
      throw new Error(reason)
    })
  })

  it('uses es7 async/await', async (done) => {
    const testPromise = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('Hello')
      }, 4)
    })

    try {
      const result = await testPromise
      expect(result).to.equal('Hello')
      done()
    } catch(err) {
      done(err)
    }
  })

  /*
  *  Higher-order function for use with async/await (last test)
  */
  const mochaAsync = fn => {
    return async (done) => {
      try {
        await fn()
        done()
      } catch (err) {
        done(err)
      }
    }
  }

  it('uses a higher order function wrap around async', mochaAsync(async () => {
    const testPromise = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('Hello')
      }, 4)
    })

    expect(await testPromise).to.equal('Hello')
  }))
})
查看更多
ゆ 、 Hurt°
6楼-- · 2020-01-27 01:27

What worked very well for me icm Mocha / Chai was the fakeTimer from Sinon's Library. Just advance the timer in the test where necessary.

var sinon = require('sinon');
clock = sinon.useFakeTimers();
// Do whatever. 
clock.tick( 30000 ); // Advances the JS clock 30 seconds.

Has the added bonus of having the test complete quicker.

查看更多
不美不萌又怎样
7楼-- · 2020-01-27 01:30

I asked the same thing in the Mocha mailing list. They basically told me this : to write asynchronous test with Mocha and Chai :

  • always start the test with if (err) done(err);
  • always end the test with done().

It solved my problem, and didn't change a single line of my code in-between (Chai expectations amongst other). The setTimout is not the way to do async tests.

Here's the link to the discussion in the mailing list.

查看更多
登录 后发表回答