Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angular.js how to mock(or stub) xhr request in each test

Tags:

angularjs

In angular js unit test, I wanted to set xhr response to each test(in "it" method"), not in beforeEach method, but it seems not working.?

This works

describe('ExampleListCtrl', function(){
  var $scope, $httpBackend;

  beforeEach(inject(function(_$httpBackend_, $rootScope, $controller) {
    $httpBackend = _$httpBackend_;
    $httpBackend.expectGET('examples').respond([]);   // <--- THIS ONE
    $controller(ExampleListCtrl, {$scope: $scope = $rootScope.$new()});
  }));

  it('should create "examples"  with 0 example fetched', function() {
    expect($scope.examples).toBeUndefined();
    $httpBackend.flush();
    expect($scope.examples).toEqual([]);
  });

});

result

Executed 8 of 8 SUCCESS (0.366 secs / 0.043 secs)

But this fails with error when I move expectGet method to each method. I don't know why.

describe('ExampleListCtrl', function(){
  var $scope, $httpBackend;

  beforeEach(inject(function(_$httpBackend_, $rootScope, $controller) {
    $httpBackend = _$httpBackend_;
    $controller(ExampleListCtrl, {$scope: $scope = $rootScope.$new()});
  }));

  it('should create "examples"  with 0 example fetched', function() {
    $httpBackend.expectGET('examples').respond([]);  // <--- MOVED TO HERE
    expect($scope.examples).toBeUndefined();
    $httpBackend.flush();
    expect($scope.examples).toEqual([]);
  });
});

Here is the error

....
at /Users/me/app/test/unit/controllers/ExampleListCtrlSpec.js:3:1
      Error: No pending request to flush
at Error (<anonymous>)
at Function.$httpBackend.flush (/Users/me/app/test/lib/angular/angular-mocks.js:1171:34)
at null.<anonymous> (/Users/me/app/test/unit/controllers/ExampleListCtrlSpec.js:14:18)

---- Edited ----

Following the advice below, I have moved the controller out of beforeEach, and changed test like this, so that I can test $httpBackend.expectGET more than once.

describe('ExampleListCtrl', function(){
  var $scope, $rootScope, $httpBackend;

  beforeEach(inject(function(_$httpBackend_, $rootScope, $controller) {
    $httpBackend = _$httpBackend_;
    controller = $controller;
    $scope = $rootScope.$new();
  }));

  it('should create "examples" model with 0 example fetched from xhr', function() {
    $httpBackend.expectGET('examples').respond([]);
    controller(ExampleListCtrl, {$scope: $scope});
    $httpBackend.flush();
    expect($scope.examples).toEqual([]);
  });

});
like image 521
allenhwkim Avatar asked Apr 12 '13 22:04

allenhwkim


1 Answers

This happens because once you instantiate your controller, it fetches $http and, thus, $httBackend. So, all expectations shall be made prior to requiring it.

If you wish to move your $httpBackend.expectGet to the spec (it block) then you need to move your $controller(ExempleListCtrl, ... as well, after the expectations.

like image 51
Caio Cunha Avatar answered Sep 27 '22 15:09

Caio Cunha