如何在Jasmine单元测试中解决$q.all承诺?

32

我的控制器代码如下:

$q.all([qService.getData($scope.id), dService.getData(), qTService.get()])
.then(function (allData) {
  $scope.data1 = allData[0];
  $scope.data2 = allData[1];
  $scope.data3 = allData[2];
});

在我的单元测试中,我正在做这样的事情:

beforeEach(inject(function($rootScope, $q, $location){// and other dependencies... 
  qServiceSpy = spyOn(_qService, 'getData').andCallFake(function () {
    var data1 = {
      id: 1,
      sellingProperty: 1,
    };
    var d = $q.defer();
    d.resolve(data1);
    return d.promise;
  });

  dServiceSpy = spyOn(_dService, 'getData').andCallFake(function () {
    var data2 = [{ "id": "1", "anotherProp": 123 }];
    var d = $q.defer();
    d.resolve(data2);
    return d.promise;
  });
  qTServiceSpy = spyOn(_qTService, 'get').andCallFake(function () {
    var data3 = [{ id: 0, name: 'Rahul' }];
    var d = $q.defer();
    d.resolve(data3);
    return d.promise;
  });
  rootScope = $rootScope;
});

现在在我的测试中,我正在检查服务是否被调用并且data1、data2不是未定义的。

it('check if qService' got called, function() {
  expect(scope.data1).toBeUndefined();
  rootScope.$digest();
  expect(_quoteService.getQuote).toHaveBeenCalled();
});
it('check if "data1" is defined', function () {
  expect(scope.data1).toBeUndefined();
  rootScope.$digest();
  expect(scope.data1).toBeDefined();
});
我的问题是,在控制器中使用了 q.all 和在测试中将 scope.$apply 替换为 rootScope.$digest 后,之前正常运行的代码出现了问题。使用 q.all 和 rootScope.$digest(也尝试过使用 scope.$apply),两个测试都会失败并显示以下错误信息:

10 $digest() iterations reached. Aborting!

如果我删除 rootScope.$digest,那么 promises 就永远不会被解决,测试就会失败并显示以下错误信息:

expected undefined to be defined.

有什么帮助可以让我如何使用 q.all 进行单元测试代码?我看到了这篇文章:this post,但那也没有帮助,因为我已经尝试使用 $digest
1个回答

62

您可以尝试将$rootScope.$apply()放入afterEach()回调函数中。在Angular中,承诺会在$apply()上解决。

afterEach(function(){
    rootScope.$apply();
});

3
如果你想知道这些内容的文档在哪里:Kris Kowal's Q 和 $q 的区别 & 测试 - the_karel
14
$apply通常会接收一个回调函数。我更喜欢使用scope.$digest(),它只会对当前的作用域进行脏检查,因此性能更好。 - Frank van Wijk
afterEach 对我来说已经足够了。我只是在 afterEach() 函数内测试了 Promise,它起作用了。谢谢! - messerbill
我个人遇到了一个奇怪的行为。 我有3个承诺。在添加afterEach...rootScope.$apply()之前,没有一个起作用。之后只有其中一个起作用。 - Gabriel
scope.digest是否解决所有的Promise?即使是嵌套的Promise?还是我需要多次调用它才能让代码继续执行? - Edward
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接