angular mock的httpBackend如何在测试中隐式传递给$ controller服务?

时间:2016-06-17 22:23:27

标签: angularjs dependency-injection httpbackend angular-mock

这个规范通过,即使它看起来应该失败。 (代码来自角和轨道的书)

这是角度应用:

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

并且,这是Jasmine规范:

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

});

我不明白控制器是如何访问$ httpBackend服务的,注入到传递给beforeEach方法中的注入的匿名函数中。传入$ scope服务,但httpBackend不是。

2 个答案:

答案 0 :(得分:0)

$controller并不依赖于$httpBackend服务,$httpBackend没有传递给它。

$http depends on $httpBackend(因此得名)。在{mm with mocked implementation中覆盖了$httpBackend,并由$http使用而不是original $httpBackend(不打算直接使用)。

答案 1 :(得分:0)

在您的代码中:

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

您要求angular将其存储的$ http注入您的控制器。你没有在这里提供本地覆盖

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

所以Angular用它拥有的东西满足你的注射要求。正如@estus所说,ngMock中提供的覆盖本身注入$ httpBackend,你已经在测试中配置了以某种方式行动..