0

This spec passes, even though it looks like it should fail. (the code is from a book on angular and rails)

here is the angular app:

var app = angular.module('customers',[]);

app.controller("CustomerSearchController",
  ["$scope", "$http", function($scope, $http) {
    var page = 0;
    $scope.customers = [];
    $scope.search = function (searchTerm) {
      if (searchTerm.length < 3) {
        return;
      }
      $http.get("/customers.json",
        { "params": { "keywords": searchTerm, "page": page } }
      ).then(function(response) {
          $scope.customers = response.data;
        },function(response) {
          alert("There was a problem: " + response.status);
        }
      );
    };
  }
]);

and, here is the Jasmine spec:

describe("Error Handling", function () {
  var scope = null,
    controller = null,
    httpBackend = null;
  beforeEach(module("customers"));
  beforeEach(inject(function ($controller, $rootScope, $httpBackend) {
    scope = $rootScope.$new();
    httpBackend = $httpBackend;
    controller = $controller("CustomerSearchController", {
      $scope: scope
    });
  }));
  beforeEach(function () {
    httpBackend.when('GET', '/customers.json?keywords=bob&page=0').respond(500, 'Internal Server Error');
    spyOn(window, "alert");
  });
  it("alerts the user on an error", function() {
    scope.search("bob");
    httpBackend.flush();
    expect(scope.customers).toEqualData([]);
    expect(window.alert).toHaveBeenCalledWith(
      "There was a problem: 500");
    });

});

I don't understand how the controller is ever getting access to the $httpBackend service, injected into the anonymous function passed to inject in the beforeEach method. The $scope service is passed in, but httpBackend isn't.

Leo D
  • 209
  • 2
  • 5

2 Answers2

0

$controller doesn't depend on $httpBackend service, $httpBackend isn't passed to it.

$http depends on $httpBackend (hence the name). $httpBackend is overridden in ngMock with mocked implementation and used by $http instead of the original $httpBackend (which isn't intended for direct use).

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
0

In your code:

app.controller("CustomerSearchController",
  ["$scope", "$http", function($scope, $http) {
     ...
   }]
)

You are asking angular to inject the $http that it has on file into your controller. You did not provide a local override here

controller = $controller("CustomerSearchController", {
      $scope: scope
    });

so Angular fulfills your injection request with what it has. As @estus says, the override provided in ngMock is itself injected with $httpBackend, which you have configured in your test to act a certain way..

Amy Blankenship
  • 6,485
  • 2
  • 22
  • 45