当使用Chai作为承诺时,我是否真的需要在测试中返回一个承诺?(Do I really need to return a promise in test when using Chai as Promised?)

264 IT屋

Chai as Promised documentation states as follows:

Notice: either return or notify(done) must be used with promise assertions.

And the examples on the site are as follows:

return doSomethingAsync().should.eventually.equal("foo");

doSomethingAsync().should.eventually.equal("foo").notify(done);

The thing is; I actually wrote a test using chai as promised without returning the promise. Like so:

it('should resolve user', function () {
    $state.get(state).resolve.user(dataservice, {
      userId: testUser.id
    }).should.eventually.eq(testUser);
    $rootScope.$apply();
  });

And it works perfectly fine. I am sure it does as I change testUser to something else the test fails. Just like I expected. So I am not sure if I am doing something wrong here.

In fact, when I modified the code to return a promise, it failed with error "Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test." The modified code is below:

it('should resolve user', function () {
    var promise = $state.get(state).resolve.user(dataservice, {
      userId: testUser.id
    }).should.eventually.eq(testUser);
    $rootScope.$apply();
    return promise;
  });

A little confused here. It might have something to do with Angular $q. To make it clear, the function resolve.user returns a $q promise.

解决方案

In the case above Mocha chains returned promise after $rootScope.$apply() was called, so chained then needs another $rootScope.$apply() to be executed. Without this the rest of promise chain is not executed and results in timeout.

Returning promises in Mocha specs is intended for asynchronous specs, this is necessary for testing non-Angular promises. $q promises are synchronous and tied to Angular digests.

As shown here, chai-as-promised can be modified to support $q promises and apply $rootScope.$apply() automatically to asserted promises:

chaiAsPromised.transferPromiseness = function (assertion, promise) {
  assertion.then = promise.then.bind(promise);

  if (!('$$state' in promise))
    return;

  inject(function ($rootScope) {
    if (!$rootScope.$$phase)
      $rootScope.$digest();
  });
};

Chai承诺的文件如下:




注意:return或notify(done)必须与promise断言一起使用。




该网站上的示例如下:




  return doSomethingAsync()。should.eventually.equal(foo); 

doSomethingAsync()。should.eventually.equal(foo)。notify(done);



事情是这样的;我实际上是按照承诺使用chai编写了一个测试而没有返回承诺。像这样:



  it('应该解析用户',函数(){
$ state.get(state) .resolve.user(dataservice,{
userId:testUser.id
})。should.eventually.eq(testUser);
$ rootScope。$ apply();
} );


它完全正常。我确信它会将testUser更改为其他测试失败的内容。就像我预期的那样。所以我不确定我在这里做错了什么。



事实上,当我修改代码以返回一个promise时,它失败并出现错误Error:timeout of超过2000ms。确保在此测试中调用done()回调。修改后的代码如下:



  it('应该解析用户',函数(){
var promise = $ state.get(state).resolve.user(dataservice,{
userId:testUser.id
})。should.eventually.eq(testUser);
$ rootScope。$ apply() ;
返回承诺;
});


这里有点困惑。它可能与Angular $ q有关。为清楚起见,函数resolve.user返回一个$ q的承诺。


解决方案

在上面的情况下,摩卡链返回了承诺后 $ rootScope。$ apply()被调用,因此链接然后需要另一个 $ rootScope。要执行$ apply()。如果没有这个,其余的promise链就不会执行并导致超时。



Mocha规范中的返回承诺是针对异步规范的,这对于测试非Angular承诺是必要的。 $ q 承诺是同步的并且与Angular摘要相关联。



如图所示在哪里, chai-as-promised 以支持 $ q 承诺并自动应用 $ rootScope。$ apply()断言承诺:



  chaiAsPromised.transferPromiseness = function(断言,承诺){
assertion.then = promise.then。绑定(承诺);

if(!(承诺中的'$$ state'))
return;

inject(函数($ rootScope){
if(!$ rootScope。$$ phase)
$ rootScope。$ digest();
});
};

本文地址:IT屋 » 当使用Chai作为承诺时,我是否真的需要在测试中返回一个承诺?