【问题标题】:$httpBackend.flush() method throws Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting$httpBackend.flush() 方法抛出错误:[$rootScope:infdig] 达到了 10 个 $digest() 迭代。中止
【发布时间】:2016-02-25 15:08:18
【问题描述】:

我正在尝试使用 Karma 和 Jasmine 对我的 AngularJS 应用程序进行单元测试。我想模拟 $http 服务。为此,我使用了 $httpBackend 方法。以下是我要测试的服务:

angular.module('MyModule').factory('MyService', function($http, $log, $parse, $q, $timeout, $filter, MyOtherService1, MyOtherService2){
var service = {};
   service.getSomething = function(id){
     return $http.get('/somePath/subpath/' + id);
   }
});

我对此服务的单元测试是:

describe("myTest", function(){
    var myService, $httpBackend, scope, mockMyOtherService1, mockMyOtherService2;

    var myResponse =
    {
        foo:'bar'
    };

    beforeEach(module("MyModule"));

    beforeEach(inject(function(_MyService_, $injector){

        $httpBackend = $injector.get('$httpBackend');
        myService = _MyService_;
        scope = $injector.get('$rootScope').$new();
        mockMyOtherService1 = $injector.get('MyOtherService1');
        mockMyOtherService2 = $injector.get('MyOtherService2');

    }));

    beforeEach(function(){
        //To bypass dependent requests
        $httpBackend.whenGET(/\.html$/).respond(200,'');
    });

    //If I uncomment the below afterEach block, the same error is shown at next line.
    /*afterEach(function() {
         $httpBackend.verifyNoOutstandingExpectation();
         $httpBackend.verifyNoOutstandingRequest();
     });*/

    //This test passes successfully
    it("should check if service is instantiated", function () {
        expect(myService).toBeDefined();
    });

    //This test passes successfully
    it("should expect dependencies to be instantiated", function(){
        expect($httpBackend).toBeDefined();
    });

    //The problem is in this test
    it("should get the getSomething with the provided ID", function() {
        $httpBackend.whenGET('/somePath/subpath/my_123').respond(200,myResponse);            
        var deferredResponse = myService.getSomething('my_123');

        //The error is shown in next line.
        $httpBackend.flush();      

        //If I comment the $httpBackend.flush(), in the next line, the $$state in deferredResponse shows that the Object that I responded with is not set i.e. it does not matches the 'myResponse'.
        expect(deferredResponse).toEqual(myResponse);

    });
});

这是一个紧急问题,我需要尽快获得帮助。非常感谢您的回答。

【问题讨论】:

    标签: angularjs unit-testing karma-jasmine httpbackend ngmock


    【解决方案1】:

    我最近在将项目从 Angular 1.2 更新到 1.4 时遇到了这个问题。测试代码看起来像:

    it('should call /something', function(){
        httpBackend.expectGET('/something').respond(200);
        scope.doSomething();
        httpBackend.flush();
    });
    

    错误是过去 10 次迭代的 infdig。它是由调用.flush() 方法引起的。我发现这似乎是因为在 doSomething() 中没有创建待处理的承诺。

    一旦我在 doSomething() 或内部方法中的某处添加了一个承诺,infdig 问题就消失了。

    我怀疑——这是 100% 的猜测,所以不要让它影响你的开发——这是因为 httpBackend 会采取一些诡计来等待承诺,这可能涉及反复消化直到发生变化。由于没有承诺,所以没有变化 - 无限摘要。

    【讨论】:

      【解决方案2】:

      问题是我需要在我的规范文件中注入 $location,即使它们没有注入到服务中。注射后,一切正常!希望这可以帮助陷入相同情况的人。

      【讨论】:

      • @TusharRaj 您面临的具体问题是什么?请指出你关于stackoverflow的问题
      【解决方案3】:

      您将从您的服务中获得承诺。因此,将您的测试代码更改为:

      //The problem is in this test
      it("should get the getSomething with the provided ID", function (done) {
        $httpBackend.expectGET('/somePath/subpath/my_123').respond(200,myResponse);
        var deferredResponse = myService.getSomething('my_123');
      
        deferredResponse.then(function (value) {
          expect(value.data).toEqual(myResponse);
        }).finally(done);
      
        $httpBackend.flush();
      });
      

      【讨论】:

      • 我尝试了您的代码,但它给出了相同的错误,因为错误位于 $httpBackend.flush() 行。它不会在该行本身之后执行。如果我注释掉 $httpBackend.flush() 行,那么它可以工作。但我需要 $httpBackend.flush() 和 afterEach() 块。
      • 我更新了答案,将 flush() 调用移到了末尾。它现在可以在我的机器上运行。你能用更新后的代码再试一次吗?
      • 还是同样的错误!我想我忽略了一些东西,但我无法找到它。即使我不写任何 it() 块, afterEach() 应该可以工作,但它也不能工作!因此,我不得不将其注释掉并继续进行。但即便如此,我仍被困在 $httpBackend.flush()!
      • 问题标题中提到的相同错误。如果我从@ogugger 提供的代码中注释掉 $httpBackend.flush() 行,那么我会得到 错误:超时 - 在 jasmine.DEFAULT_TIMEOUT_INTERVAL 指定的超时内未调用异步回调。。自 3 天以来,我一直被这个问题困扰,我也检查了 Google 和 Stackoverflow 上的许多资源,但没有一个有效。也许这是一些逻辑错误,因为我对此很陌生。我请求您查看我创建的服务,如果有任何问题。
      • 尝试删除其他服务(MyOtherService1、MyOtherService2),这样您就只有您发布的代码,然后进行我的更改。它的行为方式仍然相同吗?
      猜你喜欢
      • 1970-01-01
      • 2015-11-11
      • 1970-01-01
      • 2018-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-14
      相关资源
      最近更新 更多