Mocha 测试不会解决使用 Sinon 存根的承诺

Mocha test will not resolve promise using Sinon stub

我正在使用 Mocha 测试一个内部有异步方法的方法。我正在用 Sinon 消除这种依赖,并返回一个已解决的承诺。但是承诺永远不会解决,或者至少当断言是 运行 时它还没有解决。

下面是正在测试的方法

function identify(traits) {
  //THIS GETS CALLED SUCCESSFULLY
  userService.get().then(function(user){
    //CODE NEVER REACHES HERE

    userService.set(user).then(function(){
      //do something
    }, function(){
      //handle error
    });
  });
}

这是测试

it('should identify a valid email address', function(){
  var user =  { email: 'test@example.com' };
  var getUserStub = sinon.stub(userService, "get");
  var setUserStub = sinon.stub(userService, "set");
  var userReturn = { email: 'test@example.com', urls: ['http://some.url.com'] };

  getUserStub.returns(Promise.resolve(userReturn));

  //THE METHOD UNDER TEST
  identifyController.identify(user);

  sinon.assert.calledOnce(userService.get);  //WORKS FINE
  sinon.assert.calledOnce(userService.set);  //FAILS
  getUserStub.restore();
});

userService.set 断言失败,它说它被调用了 0 次。我做错了什么?

终于找到问题了

Promise 本质上是异步的,但 sinon 调用是同步的。

看到这个code pen

会发生什么:

  1. 你打电话给identifyController.identify(user);
    • 它会调用 get,returns 一个 promise,它是 asyncrhonous
  2. 程序的主线程仍将是 运行,因此您的两个 sinon.assert.calledOnce 调用将按顺序发生,同步

get 自行解析并调用 set 时,因为承诺是 non-blocking,断言已经执行,所以它会失败。

所以,你可以这样做:

function identify(traits) {
  return userService.get().then(function(user){
    console.log('get');    
    userService.set(user).then(function(){
      console.log('set');
      //do something
    });
  });
}

并更改此:

identify(user).then(function(){
  sinon.assert.calledOnce(myObj.get);  //WORKS FINE
  sinon.assert.calledOnce(myObj.set);  //WORKS FINE NOW
});