如何在Promise中的异步函数中断言?

时间:2016-11-06 06:18:43

标签: javascript unit-testing asynchronous promise mocha

当使用Mocha进行单元测试时,我需要测试这样的情况:

it('should assert true blah blah blah', function () {

  return doSomething() // <-- returns a Promise
    .then(function(value) {

      return setTimeout(function() {

        assert.equal(something, true);

      },1000);

    });

});

所以我有一个从函数返回的Promise,然后我需要在Promise解析后在异步setTimeout内执行断言。无论如何,上面的代码似乎总是通过测试。事实上,似乎setTimeout从未运行过。如果我在console.log中放置setTimeout,它就永远不会打印出来。摩卡完成单元测试并继续前进。

测试这样的东西的正确方法是什么?我看到摩卡有某种done()方法,但我不确定这是否应该与我一起使用。我不完全理解它。

3 个答案:

答案 0 :(得分:1)

如果您向Mocha返回一个承诺,那么当承诺结算时,它将假定测试已完成。

如果你有一些非承诺的异步函数在promise解析后进行测试,你可以使用done回调代替返回一个承诺:

it('should assert true blah blah blah', function (done) {

  doSomething()
    .then(function(value) {

      setTimeout(function() {

        assert.equal(something, true);
        done();

      },1000);

    })
    .catch(done);
});

请注意,您还应该包含catch,以便将任何承诺拒绝传递给done回调,因为Mocha了解节点样式错误,如果收到错误,将无法通过测试。

或者,您可以使用完全基于承诺的方法,并可以创建一个Promise来封装您的异步函数:

it('should assert true blah blah blah', function () {

  return doSomething()
    .then(function(value) {

      return new Promise(function (resolve, reject) {

        setTimeout(function() {

          try {
            assert.equal(something, true);
            resolve();
          } catch (error) {
            reject(error);
          }

        },1000);

      });
    });
});

答案 1 :(得分:0)

您无需使用setTimeout()来“等待”Promise得到解决。相反,当Promise得到解决时,.then()将被调用。你只需使用value或在那里做一些assert就可以了。

答案 2 :(得分:0)

因为Mocha可以使用intelligently with functions that return Promises,您还可以使用新的async / await语法,隐式返回Promises!

import 'babel-polyfill';

it('should assert true blah blah blah', async function () {
  // `doSomething` is a function that returns a Promise
  // `something` will be the resolved value
  let something = await doSomething();
  assert.equal(something, true);
});

需要进行一些设置,但我认为考虑到最终测试代码看起来多么美观和平整,这是值得的。而且写起来非常容易。

您可能希望以下软件包 - es2015es2016在此处是可选的,但如果您正在编写测试代码,则可能还包括这些代码。无论如何,你最终都会想要他们。 babel-register用于require钩子,babel-polyfill用于再生器运行时。

$ npm install --save-dev babel-cli           \
                         babel-register      \
                         babel-polyfill      \
                         babel-preset-es2015 \
                         babel-preset-es2016 \
                         babel-preset-es2017

您的 .babelrc

{
  "presets": ["es2015", "es2016", "es2017"]
}

您的 package.json

{
  "scripts": {
    "test": "mocha --compilers js:babel-register"
  }
}