Node.js Assert正在破坏Mocha测试中的异步函数

Node.js Assert正在破坏Mocha测试中的异步函数,node.js,testing,promise,mocha.js,Node.js,Testing,Promise,Mocha.js,我正在构建一个节点模块,并尽我所能对其进行单元测试。我已经安排摩卡和柴做测试处理。我在测试异步方法(返回承诺的方法)时遇到问题 在下面的测试中,我正在“升级”对象上测试一个方法 getVersions()调用返回一个承诺,因为该方法是异步的。当承诺解析时,我想测试versions变量中返回的值 assert(versions&&versions.length>0,'应该至少有一个版本')是实际测试。我添加了assert.equal(1,2)

我正在构建一个节点模块,并尽我所能对其进行单元测试。我已经安排摩卡和柴做测试处理。我在测试异步方法(返回承诺的方法)时遇到问题

在下面的测试中,我正在“升级”对象上测试一个方法

getVersions()
调用返回一个承诺,因为该方法是异步的。当承诺解析时,我想测试
versions
变量中返回的值

assert(versions&&versions.length>0,'应该至少有一个版本')是实际测试。我添加了
assert.equal(1,2)
我假设assert调用抛出了一个Mocha应该接收的异常。然而,它被困在promises
then
handler函数中


这是怎么回事?为什么当断言将在该方法中失败时,它不会在列表中显示测试用例(它不会显示为失败;就像它不存在一样)?

在调用回调之前,测试不会显示在列表中,如果断言失败,则决不会发生这种情况。您需要在最终承诺中调用
.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);
    });
  });

问题的核心在于,您拥有的代码基本上是:

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()

这就是说,将承诺作为回报要容易得多

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
});

让摩卡在没有回调的情况下监控承诺本身。

我不知道为什么这个答案有效。原始代码基本上是:async().then(function(){throw new Error();//如果此行抛出,则传递给.catch()处理程序done();})。catch(done)//将done()注册为错误处理程序。如果发生抛出,则不会执行
then()
处理程序中的
done()
调用,而是调用
.catch()
处理程序。。。这仍然是
完成的
。哎哟,注释不允许代码块和5分钟后锁定。很抱歉,这是一个垃圾格式:(
.then(fn,done)
.then(fn).catch(done);
,这是区别的核心。在第一个if
fn
抛出时,这是一个未处理的错误,在第二个示例中,调用了
done
。您的意思是当代码在里面时。then()如果失败,它将不会触发第二个参数?是的,确实如此,因此在问题中,
assert
抛出而
done
从未被调用,因此解决方案是将
done
处理程序移动到始终被调用的位置,无论是错误还是其他。
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
});