5

我正在尝试测试一个返回承诺的方法调用,但是我遇到了麻烦。这在 NodeJS 代码中,我使用 Mocha、Chai 和 Sinon 来运行测试。我目前的测试是:

it('should execute promise\'s success callback', function() {
  var successSpy = sinon.spy();

  mySpies.executeQuery = sinon.stub(databaseConnection, 'execute').returns(q.resolve('[{"id":2}]'));

  databaseConnection.execute('SELECT 2 as id FROM Users ORDER BY RAND() LIMIT 1').then(successSpy, function(){});

  chai.expect(successSpy).to.be.calledOnce;

  databaseConnection.execute.restore();
});

但是,此测试出错:

AssertionError: expected spy to have been called exactly once, but it was called 0 times

测试返回承诺的方法的正确方法是什么?

4

2 回答 2

7

then() 调用的处理程序不会在注册期间被调用 - 仅在下一个事件循环期间,它在您当前的测试堆栈之外。

您必须在完成处理程序中执行检查并通知 mocha 您的异步代码已完成。另见http://visionmedia.github.io/mocha/#asynchronous-code

它应该看起来像这样:

it('should execute promise\'s success callback', function(done) {
  mySpies.executeQuery = sinon.stub(databaseConnection, 'execute').returns(q.resolve('[{"id":2}]'));

  databaseConnection.execute('SELECT 2 as id FROM Users ORDER BY RAND() LIMIT 1').then(function(result){
    chai.expect(result).to.be.equal('[{"id":2}]');
    databaseConnection.execute.restore();
    done();
  }, function(err) {
    done(err);
  });
});

对原始代码的更改:

  • 测试函数的 done 参数
  • then() 处理程序中的检查和清理

编辑:另外,老实说,这个测试并没有测试任何关于你的代码的东西,它只是验证承诺的功能,因为你的代码(数据库连接)的唯一部分正在被删除。

于 2013-09-03T13:45:47.940 回答
1

I recommend checking out Mocha As Promised

It allows for a much cleaner syntax than trying to execute done() and all that nonsense.

it('should execute promise\'s success callback', function() {
    var successSpy = sinon.spy();

    mySpies.executeQuery = sinon.stub(databaseConnection, 'execute').returns(q.resolve('[{"id":2}]'));

    // Return the promise that your assertions will wait on
    return databaseConnection.execute('SELECT 2 as id FROM Users ORDER BY RAND() LIMIT 1').then(function() {
        // Your assertions
        expect(result).to.be.equal('[{"id":2}]');
    });

});
于 2013-12-21T22:05:47.247 回答