Unable to use httpBackend flush for ngMockE2E

216 views Asked by At

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

There are 2 answers

5
danday74 On BEST ANSWER

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.

0
ngstschr On

The angular documentation says the following about $httpbackend for ngMockE2E:

Additionally, we don't want to manually have to flush mocked out requests like we do during unit testing. For this reason the e2e $httpBackend flushes mocked out requests automatically, closely simulating the behavior of the XMLHttpRequest object.

So, short answer: it doesn't exist and you don't need it.