在使用ngMock时,为什么$ q.when在解包第三方承诺时无法解决?

时间:2015-09-16 13:17:11

标签: angularjs unit-testing jasmine promise angular-promise

鉴于以下服务:

2015-09-16 18:24:52 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).

......以及以下测试:

angular.module('app', [])
  .service('promisey', function ($q) {
    this.cakey = function () {
      return $q.when('brownie')
    }
    this.fruity = function () {
      return $q.when(Promise.resolve('apple'))
    }
  })

...来源var self = this describe('when', function () { var promisey var $rootScope beforeEach(module('app')) beforeEach(inject(function(_$rootScope_, _promisey_) { promisey = _promisey_ $rootScope = _$rootScope_ })) it('should give cakes', function (done) { promisey.cakey() .then(function (cake) { expect(cake).toBe('brownie') }) .catch(self.fail.bind()) .finally(done) $rootScope.$apply() }) it('should give fruit', function (done) { promisey.fruity() .then(function (cake) { // XXX: does not resolve expect(cake).toBe('apple') }) .catch(self.fail.bind()) .finally(done) $rootScope.$apply() }) }) 时,ngMock永远无法解决。如果我没有提供promisey.fruity()(并自行处理ngMock),则测试将按预期解决。那是为什么?

可以在tlvince/q-when-reduced-test-case找到此问题的简化测试用例。

1 个答案:

答案 0 :(得分:3)

这是因为本机承诺使用与Angular不同的调度程序。 Angular schedule通过evalAsync在其异步队列上进行承诺。不同的承诺库可能会以不同的方式安排承诺 - 在本机承诺的使用情况下,它通过称为"微任务队列"。

的东西进行调度。

当您致电$rootScope.$apply时,它会刷新evalAsync队列"由于运行了摘要周期,因此可以模拟" async"并让你测试承诺。

你不能欺骗"这种方式使用本机承诺定时器,因此您必须编写一个实际上异步的测试。

您无法使用ngMock并使用Mocha的承诺语法:

  it('should give fruit', function () { // no done
    return promisey.fruity() // see return here
      .then(function (cake) {
        expect(cake).toBe('apple')
      });
      // no digest, no `done`
  });

我认为它看起来好多了:))