断言正在破坏 Mocha 测试中的异步功能
Posted
技术标签:
【中文标题】断言正在破坏 Mocha 测试中的异步功能【英文标题】:Assert Is Breaking Async Function in Mocha Test 【发布时间】:2015-03-26 16:33:04 【问题描述】:我正在构建一个节点模块,并尽我所能对它进行单元测试。我已经设置了 mocha 和 chai 来进行测试处理。我在测试我的异步方法(返回承诺的方法)时遇到问题。
在下面的测试中,我正在“升级”对象上测试一个方法。
it('Should return a list of versions for the default git repo', function (done)
fs.writeFileSync(appSetup.CONFIG_FILENAME, JSON.stringify(appSetup.DEFAULT_CONFIG));
var upgrade = new Upgrade(
quiet: true
);
upgrade.getVersions().then(function (versions)
assert(versions && versions.length > 0, 'Should have at least one version.');
assert.equal(1, 2); // this throws the exception which causes the test case not even exist
done();
, done);
);
getVersions()
调用返回一个承诺,因为该方法是异步的。当承诺解决时,我想测试 versions
变量中返回的值。
assert(versions && versions.length > 0, 'Should have at least one version.');
是实际测试。我添加了assert.equal(1, 2);
,因为我注意到当测试失败时,测试用例甚至不会出现在测试列表中。
我假设 assert 调用引发了 Mocha 应该拾取的异常。但是它被困在了then
处理函数中。
这里发生了什么?为什么当该方法中的断言将失败时,它不会在列表中显示测试用例(它没有显示为失败;就像它不存在一样)?
【问题讨论】:
【参考方案1】:问题的核心在于您拥有的代码本质上是:
try
var versions = upgrade.getVersions();
catch (err)
return done(err);
assert(versions && versions.length > 0, 'Should have at least one version.');
assert.equal(1, 2); // this throws the exception which causes the test case not even exist
done();
看看,应该清楚的是,如果断言抛出,那么都不回调将运行。
try
var versions = upgrade.getVersions();
assert(versions && versions.length > 0, 'Should have at least one version.');
assert.equal(1, 2); // this throws the exception which causes the test case not even exist
done();
catch (err)
return done(err);
更像你想要的,那就是:
upgrade.getVersions().then(function (versions)
assert(versions && versions.length > 0, 'Should have at least one version.');
assert.equal(1, 2); // this throws the exception which causes the test case not even exist
).then(done, done);
这将执行断言,然后将回调移动到辅助.then()
的节点,该辅助.then()
将始终处理错误。
也就是说,简单地将承诺返回为
return upgrade.getVersions().then(function (versions)
assert(versions && versions.length > 0, 'Should have at least one version.');
assert.equal(1, 2); // this throws the exception which causes the test case not even exist
);
让 Mocha 在没有回调的情况下监控 Promise 本身。
【讨论】:
我不确定我理解为什么这个答案有效。原始代码基本上是: async().then(function() throw new Error(); // 如果这一行抛出,则传递给 .catch() 处理程序 done(); ).catch(done) // 将 done() 注册为错误处理程序。如果发生抛出,则不会执行then()
处理程序中的 done()
调用,而是调用 .catch()
处理程序......仍然是 done
。
哎呀,cmets 不允许代码块并在 5 分钟后锁定。对不起,废话格式:(
.then(fn, done)
不等于.then(fn).catch(done);
,这是区别的核心。第一个如果fn
抛出,这是一个未处理的错误,在第二个例子中,done
被调用。
你的意思是说当.then()里面的代码失败时,它不会触发第二个参数?
是的,所以在问题中assert
抛出并且done
永远不会被调用,所以解决方案是移动done
处理程序以始终被调用,无论错误或其他情况。跨度>
【参考方案2】:
在您调用回调之前,测试不会显示在列表中,如果断言失败,则永远不会发生这种情况。您需要在最终承诺中调用 .catch(done)
,以确保始终调用 done
。
如果你给它一个超时值,测试将显示出来,你应该这样做。
话虽如此,mocha
理解承诺。你根本不需要处理回调:
it('Should return a list of versions for the default git repo', function ()
fs.writeFileSync(appSetup.CONFIG_FILENAME, JSON.stringify(appSetup.DEFAULT_CONFIG));
var upgrade = new Upgrade(
quiet: true
);
return upgrade.getVersions().then(function (versions)
assert(versions && versions.length > 0, 'Should have at least one version.');
assert.equal(1, 2);
);
);
【讨论】:
以上是关于断言正在破坏 Mocha 测试中的异步功能的主要内容,如果未能解决你的问题,请参考以下文章
异步 Mocha 测试(使用 Chai 断言库)应该失败,但被标记为通过