Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
514 views
in Technique[技术] by (71.8m points)

javascript - Do I really need to return a promise in test when using Chai as Promised?

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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();
  });
};

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...