2

请参阅此 plunkr 以获取实时示例:http ://plnkr.co/edit/djQPW7g4HIuxDIm4K8RC

在下面的代码中,该行在var promise = serviceThatReturnsPromise();模块配置期间运行,但我想模拟出服务返回的承诺。

理想情况下,我会使用该$q服务来创建模拟承诺,但我不能这样做,因为serviceThatReturnsPromise()在模块配置期间执行,然后才能访问$q. 解决这个先有鸡还是先有蛋的问题的最佳方法是什么?

var app = angular.module('plunker', []);

app.factory('serviceUnderTest', function (serviceThatReturnsPromise) {
  // We mock out serviceThatReturnsPromise in the test
  var promise = serviceThatReturnsPromise();
  return function() {
    return 4;
  };
});

describe('Mocking a promise', function() {
  var deferredForMock, service;

  beforeEach(module('plunker'));

  beforeEach(module(function($provide) {
    $provide.factory('serviceThatReturnsPromise', function() {

        return function() {
          // deferredForMock will be undefined because this is called
          // when `serviceUnderTest` is $invoked (i.e. at module configuration),
          // but we don't define deferredForMock until the inject() below because  
          // we need the $q service to create it. How to solve this chicken and
          // egg problem?
          return deferredForMock.promise;
        }
    });
  }));

  beforeEach(inject(function($q, serviceUnderTest) {
    service = serviceUnderTest;
    deferredForMock = $q.defer();
  }));

  it('This test won\'t even run', function() {
    // we won't even get here because the serviceUnderTest
    // service will fail during module configuration
    expect(service()).toBe(4);
  });
});
4

1 回答 1

2

我不确定我是否喜欢这个解决方案,但它是:

http://plnkr.co/edit/uBwsJxJRjS1qqsKIx5j7?p=preview

您需要确保在设置完所有内容后才实例化“serviceUnderTest”。因此,我将第二个beforeEach分成两个独立的部分:第一个实例化和使用$q,第二个实例化和使用serviceUnderTest

我还必须包含$rootScope,因为 Angular 的承诺旨在在$apply()方法中工作。

希望有帮助。

于 2013-04-19T12:49:44.263 回答