How to test promises with Mocha

2019-01-14 13:05发布

问题:

I'm using Mocha to test an asynchronous function that returns a promise.

What's the best way to test that the promise resolves to the correct value?

回答1:

Mocha has built-in Promise support as of version 1.18.0 (March 2014). You can return a promise from a test case, and Mocha will wait for it:

it('does something asynchronous', function() { // note: no `done` argument
  return getSomePromise().then(function(value) {
    expect(value).to.equal('foo');
  });
});

Don't forget the return keyword on the second line. If you accidentally omit it, Mocha will assume your test is synchronous, and it won't wait for the .then function, so your test will always pass even when the assertion fails.


If this gets too repetitive, you may want to use the chai-as-promised library, which gives you an eventually property to test promises more easily:

it('does something asynchronous', function() {
  return expect(getSomePromise()).to.eventually.equal('foo');
});

it('fails asynchronously', function() {
  return expect(getAnotherPromise()).to.be.rejectedWith(Error, /some message/);
});

Again, don't forget the return keyword!



回答2:

Then 'returns' a promise which can be used to handle the error. Most libraries support a method called done which will make sure any un-handled errors are thrown.

it('does something asynchronous', function (done) {
  getSomePromise()
    .then(function (value) {
      value.should.equal('foo')
    })
    .done(() => done(), done);
});

You can also use something like mocha-as-promised (there are similar libraries for other test frameworks). If you're running server side:

npm install mocha-as-promised

Then at the start of your script:

require("mocha-as-promised")();

If you're running client side:

<script src="mocha-as-promised.js"></script>

Then inside your tests you can just return the promise:

it('does something asynchronous', function () {
  return getSomePromise()
    .then(function (value) {
      value.should.equal('foo')
    });
});

Or in coffee-script (as per your original example)

it 'does something asynchronous', () ->
  getSomePromise().then (value) =>
    value.should.equal 'foo'