我想对以下 AngularJs 服务进行单元测试:
.factory('httpResponseInterceptor', ['$q', '$location', '$window', 'CONTEXT_PATH', function($q, $location, $window, contextPath){
return {
response : function (response) {
//Will only be called for HTTP up to 300
return response;
},
responseError: function (rejection) {
if(rejection.status === 405 || rejection.status === 401) {
$window.location.href = contextPath + '/signin';
}
return $q.reject(rejection);
}
};
}]);
我尝试过以下套件:
describe('Controllers', function () {
var $scope, ctrl;
beforeEach(module('curriculumModule'));
beforeEach(module('curriculumControllerModule'));
beforeEach(module('curriculumServiceModule'));
beforeEach(module(function($provide) {
$provide.constant('CONTEXT_PATH', 'bignibou'); // override contextPath here
}));
describe('CreateCurriculumCtrl', function () {
var mockBackend, location, _window;
beforeEach(inject(function ($rootScope, $controller, $httpBackend, $location, $window) {
mockBackend = $httpBackend;
location = $location;
_window = $window;
$scope = $rootScope.$new();
ctrl = $controller('CreateCurriculumCtrl', {
$scope: $scope
});
}));
it('should redirect to /signin if 401 or 405', function () {
mockBackend.whenGET('bignibou/utils/findLanguagesByLanguageStartingWith.json?language=fran').respond([{"description":"Français","id":46,"version":0}]);
mockBackend.whenPOST('bignibou/curriculum/new').respond(function(method, url, data, headers){
return [401];
});
$scope.saveCurriculum();
mockBackend.flush();
expect(_window.location.href).toEqual("/bignibou/signin");
});
});
});
但是,它失败并显示以下错误消息:
PhantomJS 1.9.2 (Linux) Controllers CreateCurriculumCtrl should redirect to /signin if 401 or 405 FAILED
Expected 'http://localhost:9876/context.html' to equal '/bignibou/signin'.
PhantomJS 1.9.2 (Linux) ERROR
Some of your tests did a full page reload!
我不确定出了什么问题以及为什么。有人可以帮忙吗?
我只想确保
$window.location.href
等于 '/bignibou/signin'
.编辑 1 :
我设法让它工作如下(感谢“dskh”):
beforeEach(module('config', function($provide){
$provide.value('$window', {location:{href:'dummy'}});
}));
最佳答案
我遇到了同样的问题,并在我的解决方案中更进一步。我不只是想要一个模拟,我想替换 $window.location.href
使用 Jasmine spy ,以便更好地跟踪对其所做的更改。所以,我从 apsiller's example for spying on getters/setters 那里学到了在创建我的模拟之后,我能够监视我想要的属性。
首先,这是一个展示我如何模拟 $window
的套件。 ,通过测试证明 spy 按预期工作:
describe("The Thing", function() {
var $window;
beforeEach(function() {
module("app", function ($provide) {
$provide.value("$window", {
//this creates a copy that we can edit later
location: angular.extend({}, window.location)
});
});
inject(function (_$window_) {
$window = _$window_;
});
});
it("should track calls to $window.location.href", function() {
var hrefSpy = spyOnProperty($window.location, 'href', 'set');
console.log($window.location.href);
$window.location.href = "https://www.google.com/";
console.log($window.location.href);
expect(hrefSpy).toHaveBeenCalled();
expect(hrefSpy).toHaveBeenCalledWith("https://www.google.com/");
});
});
正如您在上面看到的, spy 是通过调用以下函数生成的:(它适用于
get
和 set
)function spyOnProperty(obj, propertyName, accessType) {
var desc = Object.getOwnPropertyDescriptor(obj, propertyName);
if (desc.hasOwnProperty("value")) {
//property is a value, not a getter/setter - convert it
var value = desc.value;
desc = {
get: function() { return value; },
set: function(input) { value = input; }
}
}
var spy = jasmine.createSpy(propertyName, desc[accessType]).and.callThrough();
desc[accessType] = spy;
Object.defineProperty(obj, propertyName, desc);
return spy;
}
最后,here's a fiddle demonstrating this in action .我已经针对 Angular 1.4、Jasmine 2.3 和 2.4 进行了测试。
关于angularjs - 对 AngularJS $window 服务进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21645614/