angular mock 的 httpBackend 如何在测试中隐式传递给 $controller 服务?
how is angular mock's httpBackend passed implicitly to the $controller service in tests?
这个规范通过了,尽管它看起来应该失败。 (代码来自 angular 和 rails 的一本书)
这是 angular 应用程序:
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。
$controller
不依赖于 $httpBackend
服务,$httpBackend
未传递给它。
$http
depends on $httpBackend
(hence the name). $httpBackend
is overridden in ngMock with mocked implementation and used by $http
instead of the original $httpBackend
(不适合直接使用)。
在您的代码中:
app.controller("CustomerSearchController",
["$scope", "$http", function($scope, $http) {
...
}]
)
您要求 angular 将文件中的 $http 注入您的控制器。您没有在此处提供本地覆盖
controller = $controller("CustomerSearchController", {
$scope: scope
});
所以Angular用它所拥有的满足你的注入请求。正如@estus 所说,ngMock 中提供的覆盖本身注入了 $httpBackend,您已在测试中将其配置为以某种方式运行..
这个规范通过了,尽管它看起来应该失败。 (代码来自 angular 和 rails 的一本书)
这是 angular 应用程序:
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。
$controller
不依赖于 $httpBackend
服务,$httpBackend
未传递给它。
$http
depends on $httpBackend
(hence the name). $httpBackend
is overridden in ngMock with mocked implementation and used by $http
instead of the original $httpBackend
(不适合直接使用)。
在您的代码中:
app.controller("CustomerSearchController", ["$scope", "$http", function($scope, $http) { ... }] )
您要求 angular 将文件中的 $http 注入您的控制器。您没有在此处提供本地覆盖
controller = $controller("CustomerSearchController", { $scope: scope });
所以Angular用它所拥有的满足你的注入请求。正如@estus 所说,ngMock 中提供的覆盖本身注入了 $httpBackend,您已在测试中将其配置为以某种方式运行..