2

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.

4

1 回答 1

2

在上面的例子中,Mocha 链在$rootScope.$apply()被调用后返回了 Promise,所以 chainedthen需要另一个$rootScope.$apply()被执行。如果没有这个,承诺链的其余部分将不会执行并导致超时。

在 Mocha 规范中返回 Promise 是为异步规范设计的,这对于测试非 Angular 的 Promise 是必要的。$qPromise 是同步的,并且与 Angular 摘要相关联。

如此处所示,chai-as-promised可以修改为支持$qPromise 并$rootScope.$apply()自动应用于断言的 Promise:

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

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

  inject(function ($rootScope) {
    if (!$rootScope.$$phase)
      $rootScope.$digest();
  });
};
于 2016-06-22T20:00:25.343 回答