使用生成器函数的mocha测试中的无声错误

时间:2016-05-19 07:29:58

标签: javascript mocha co

我想对一个函数进行单元测试。 在那个函数中,我使用Co和生成器函数。 当发生错误时我抓住它,然后用错误

调用cb

在我的单元测试中,我做了一个错误的断言,但摩卡没有报告它,它只是超时:

//function to test

function start(data, cb) {
  co(function * coStart() {
    yield Promise.reject('err'); // yield error for sake of demo
  }).then(function(result){
    return cb(null, result);
  }).catch(function (err) {
    // we get here
    return cb(err);
  });
}

// mocha test

it('fails on incorrect data', function(done){
  MyModel.start({'foo': 'bar'}, function(err, res){
    assert.equal(err, 'err2'); //this fails but mocha just stops here and times out
    done();
  });
});

显然我在这里做错了什么?

我知道你可以在测试中返回对mocha的承诺并省略完成回调,但我的函数'start'不能返回一个promise,它就像中间件一样,所以它应该与回调一起工作

1 个答案:

答案 0 :(得分:1)

您的代码与此类似:

Promise.reject('err')
       .catch(() => {
         // throw another exception
         throw 'foo';
       });

即:在.catch()子句中,抛出另一个异常(在您的情况下,由assert.equal(err, 'err2')引发的异常),同步,未被处理(例如,另一个.catch()子句)。这将导致忽略第二个异常(请参阅this answer以获得解释),但它将阻止测试用例完成(从未到达done()行,从而超时测试用例)。

如果你真的需要回调支持,你可以通过在.catch()中添加另一个start()子句,或者通过异步调用回调来解决这个问题:

return setImmediate(function() { cb(null, result) });
...
return setImmediate(function() { cb(err) });
...

但理想情况下,您应该考虑完全删除回调支持的可能性,并且只是绕过承诺。 Mocha支持开箱即用的承诺,因此代码看起来像这样:

function start(data) {
  return co(function * coStart() {
    yield Promise.reject('err');
  });
}

it('fails on incorrect data', function(){
  return start({'foo': 'bar'}).then(function() {
    throw new Error('should not be reached');
  }, function(err) {
    assert.equal(err, 'err2');
  });
});