Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

$httpBackend.flush() method throws Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting

I am trying to unit test my AngularJS application using Karma and Jasmine. I want to mock the $http service. For that, I am using the $httpBackend method. Below is my service that I want to test:

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);
   }
});

My unit test for this service is:

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);

    });
});

This is an emergency problem and I need help regarding the same as soon as possible. I will be very grateful for your answer.

like image 484
Jagrut Avatar asked Nov 23 '15 13:11

Jagrut


2 Answers

You will get a promise from your service. So change your test code to:

//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();
});
like image 66
ogugger Avatar answered Oct 17 '22 03:10

ogugger


The problem was I needed to inject $location in my spec files even though they are not injected in the services. After injection, all worked well! Hope this helps someone who gets stuck in the same situation.

like image 41
Jagrut Avatar answered Oct 17 '22 03:10

Jagrut