0

我想对一个函数进行单元测试。在该函数中,我将 Co 与生成器函数一起使用。当发生错误时,我会捕获它,并使用错误调用 cb

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

//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 返回一个承诺并在测试中省略完成回调,但是我的函数“开始”不能返回一个承诺,它就像中间件,所以它应该与回调一起工作

4

1 回答 1

1

您的代码执行与此类似的操作:

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

也就是说:在.catch()子句中,另一个异常被assert.equal(err, 'err2')同步抛出(在你的情况下,由 抛出的异常),它没有被处理(例如,另一个.catch()子句)。这将导致第二个异常被忽略(请参阅此答案以获取解释),但它将阻止测试用例完成(done()永远不会到达该行,因此会使测试用例超时)。

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

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

但理想情况下,您应该考虑完全删除回调支持并仅传递承诺的可能性。Mocha 支持开箱即用的 Promise,因此代码如下所示:

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');
  });
});
于 2016-05-19T08:00:39.987 回答