当使用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()
方法,但我不确定这是否应该与我一起使用。我不完全理解它。
答案 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);
});
需要进行一些设置,但我认为考虑到最终测试代码看起来多么美观和平整,这是值得的。而且写起来非常容易。
您可能希望以下软件包 - es2015
和es2016
在此处是可选的,但如果您正在编写测试代码,则可能还包括这些代码。无论如何,你最终都会想要他们。 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"
}
}