1

我尝试测试一个使用嵌套承诺的函数(假设这个函数不能更改)。为了处理这些承诺,我必须$rootScope.$digest()至少打电话两次。我想出了这个工作解决方案,$digest()每 10 毫秒调用一次。

// Set some async data to scope.key
// Note: This function is just for demonstration purposes.
//       The real code makes async calls to localForage.
function serviceCall(scope, key) {
  var d1 = $q.defer(), d2 = $q.defer();

  setTimeout(function () {
    d1.resolve('d1');
  });

  d1.promise.then(function (data) {
    setTimeout(function () {
      d2.resolve(data + ' - d2');
    }, 100); // simulate longer async call
  });

  d2.promise.then(function (data) {
    scope[key] = data;
  });
}

it('nested promises service', function (done) {
  var interval = setInterval(function () {
      $rootScope.$digest();
    }, 10),
    myKey = 'myKey',
    scope = {};

  serviceCall(scope, myKey);

  setTimeout(function () {
    expect(scope[myKey]).toEqual('d1 - d2');
    window.clearInterval(interval);
    done();
  }, 120); // What is the right timeout?
});

问题是估计消化足够时间以解决所有承诺所需的超时持续时间。如果服务对例如 localstorage 进行真正的异步调用,情况会变得更加复杂。

还有其他方法可以解决这个问题吗?有没有办法获得所有剩余的承诺?

4

1 回答 1

2

您应该使用 jasmine 间谍来模拟/存根任何外部服务调用,以便您可以控制服务何时解析/拒绝。您的服务应该有支持其内部功能的测试。

请注意,此示例并不完美,但为清楚起见已进行了缩写。

var service = jasmine.createSpyObj('service', ['call']);
var defServiceCall;
var $scope;

beforeEach(function () {
  module('myModule', function ($provide) {
    // NOTE: Replaces the service definition with mock.
    $provide.value('service', service);
  });
  inject(function($q, $rootScope) {
    $scope = $rootScope.$new();
    defServiceCall = $q.defer();
    service.call.and.returnValue(defServiceCall.promise);
  });
});
describe('When resolved', function () {
  beforeEach(function () {
    myFunctionCall(); // Sets myVar on the scope
    defServiceCall.resolve('data');
    $scope.$digest(); // NOTE: Must digest for promise to update
  });
  it('should do something awesome when resolved', function () {
    expect($scope.myVar).toEqual('data');
  });
});
于 2015-05-27T18:36:43.663 回答