Search code examples
angularjskarma-jasminehttpbackendngmocke2e

Unable to use httpBackend flush for ngMockE2E


I am trying to test my controller using jasmine. Basically, when the controller is created it will call a service to make http request. I am using httpBackend to get the fake data. When I try to run the test I always get the error "No pending request to flush". If I remove the httpBackend.flush() then the test fails because controller.data.name is undefined. Can anyone know why it happens like that? Thanks.

The code for the module is here:

var myModule = angular.module('myModule', ['ngMockE2E']);
myModule.run(function($httpBackend){
  $httpBackend.whenGET('/Person?content=Manager').respond(function (){
     var response = {'name':'Bob','age':'43'}
     return [200,response];
  })
});

The code for the service:

myModule.factory('myService',function($http){
     return {
        getData: function(position){
             return  $http.get('/Person?content='+position); 
        }
     }
});

The code for controller is:

myModule.controller('myController',function(xrefService){
    var _this = this;
    _this.data ={};
    _this.getData = function(position){
        myService.getData(position).then(function(response){
            _this.data = response.data
        });
    }
    _this.getData("Manager");
})

The code to test the controller is:

describe("Test Controller",function(){
   var controller,httpBackend,createController;
   beforeEach(module('myModule'));
   beforeEach(inject(function($controller,$httpBackend){      
      createController = function(){
         return $controller('myController');
      }
      httpBackend = $httpBackend;     
   }));
   it("should return data",function(){
      controller = createController();
      httpBackend.flush();
      expect(controller.data.name).toEqual("Bob");
   });      
})

Solution

  • you are using $httpBackend.whenGET inside "The code for the module"

    you should be using $httpBackend inside the test code as follows ...

    it("should return data",function(){
      $httpBackend.expectGET('/Person?content=Manager').respond(function (){
          var response = {'name':'Bob','age':'43'}
          return [200,response];
      })
      controller = createController();
      httpBackend.flush();
      expect(controller.data.name).toEqual("Bob");
    });      
    

    also i would advise using expectGET instead of whenGET.

    With whenGET you are saying if the request is made then response like so.

    With expectGET you are saying ... a request will be made, when it is made respond like so, if the request is not made then fail the test.

    PS if you put some console.log statements inside your controller code then you should see these log statements when you run your test suite. If not then you know your controller code is not even being hit.

    also use ..

    afterEach(function () {
          httpBackend.verifyNoOutstandingExpectation();
          httpBackend.verifyNoOutstandingRequest();
    });
    

    which will force test failure if expectations were not met.