Jasmine,AngularJS 注入后更改注入的模拟对象
Jasmine, AngularJS change injected mock object after injection
我想在不同情况下测试我的工厂,例如没有令牌、过期令牌和良好令牌。我在模拟 $window.localStorage 时遇到了麻烦。这是我的测试代码:
describe('Unit: Security Module', function () {
describe('Security factory', function() {
var windowMock, locationMock, security, $httpBackend, $http, $window, $location;
beforeEach(module('app.common.security', function($provide) {
locationMock = {
url: jasmine.createSpy().and.returnValue(true)
};
windowMock = {
localStorage: { token: false }
};
$provide.value('$location', locationMock);
$provide.value('$window', windowMock);
}));
beforeEach(inject(function(_$httpBackend_, _$window_, _$location_, _security_) {
$httpBackend = _$httpBackend_;
$window = _$window_;
$location = _$location_;
security = _security_;
}));
it("Should call location.url with '/login' if no token in localStorage", function() {
security.tokenCheck();
expect($location.url).toHaveBeenCalledWith('/login');
});
it("Should call location.url with '/login' and delete token if bad token", function() {
// Need to modify the windowMock.localStorage.token value here somehow
$httpBackend
.whenPOST('/api/tokenCheck', {token:"mockBadToken123"})
.respond (400, "Token invalid or undefined");
security.tokenCheck();
expect($location.url).toHaveBeenCalledWith('/login');
expect($window.localStorage.token).toBeUndefined();
});
});
});
我的问题是:如果我想修改 windowMock 值,是否必须像这样编写所有测试?
it("good token", function () {
module('app.common.security', function ($provide) {
locationMock = {
url: jasmine.createSpy().and.returnValue(true)
};
windowMock = {
localStorage: { token: "mockBadToken123" }
};
$provide.value('$location', locationMock);
$provide.value('$window', windowMock);
});
inject(function (_$httpBackend_, _$window_, _$location_, _security_) {
$httpBackend = _$httpBackend_;
$window = _$window_;
$location = _$location_;
security = _security_;
})
$httpBackend
.whenPOST('/api/tokenCheck', {token: "mockBadToken123"})
.respond(400, "Token invalid or undefined");
security.tokenCheck();
expect($location.url).toHaveBeenCalledWith('/login');
expect($window.localStorage.token).toBeUndefined();
});
或者有更高效的方法吗?
编辑: 工厂本身看起来像这样:
angular.module('app.common.security').factory('security', ['$http', '$window', '$location', function ($http, $window, $location) {
var Security = {};
Security.tokenCheck = function () {
if (!$window.localStorage.token) {
$location.url('/login');
return;
}
$http.post('/api/tokenCheck', {token: $window.localStorage.token})
.success(function (data) {
console.log("STUBB: set user data, login status and redirect to panel");
}).error(function (err) {
delete $window.localStorage.token;
$location.url('/login');
});
};
return Security;
}]);
为什么你在考试中没有按照你说的去做?
it("Should call location.url with '/login' and delete token if bad token", function() {
// Need to modify the windowMock.localStorage.token value here somehow
$window.localStorage = { token: "mockBadToken123" };
$location.url = jasmine.createSpy().and.returnValue(true);
$httpBackend
.whenPOST('/api/tokenCheck', {token:"mockBadToken123"})
.respond (400, "Token invalid or undefined");
security.tokenCheck();
$httpBackend.flush();
expect($location.url).toHaveBeenCalledWith('/login');
expect($window.localStorage.token).toBeUndefined();
});
我想在不同情况下测试我的工厂,例如没有令牌、过期令牌和良好令牌。我在模拟 $window.localStorage 时遇到了麻烦。这是我的测试代码:
describe('Unit: Security Module', function () {
describe('Security factory', function() {
var windowMock, locationMock, security, $httpBackend, $http, $window, $location;
beforeEach(module('app.common.security', function($provide) {
locationMock = {
url: jasmine.createSpy().and.returnValue(true)
};
windowMock = {
localStorage: { token: false }
};
$provide.value('$location', locationMock);
$provide.value('$window', windowMock);
}));
beforeEach(inject(function(_$httpBackend_, _$window_, _$location_, _security_) {
$httpBackend = _$httpBackend_;
$window = _$window_;
$location = _$location_;
security = _security_;
}));
it("Should call location.url with '/login' if no token in localStorage", function() {
security.tokenCheck();
expect($location.url).toHaveBeenCalledWith('/login');
});
it("Should call location.url with '/login' and delete token if bad token", function() {
// Need to modify the windowMock.localStorage.token value here somehow
$httpBackend
.whenPOST('/api/tokenCheck', {token:"mockBadToken123"})
.respond (400, "Token invalid or undefined");
security.tokenCheck();
expect($location.url).toHaveBeenCalledWith('/login');
expect($window.localStorage.token).toBeUndefined();
});
});
});
我的问题是:如果我想修改 windowMock 值,是否必须像这样编写所有测试?
it("good token", function () {
module('app.common.security', function ($provide) {
locationMock = {
url: jasmine.createSpy().and.returnValue(true)
};
windowMock = {
localStorage: { token: "mockBadToken123" }
};
$provide.value('$location', locationMock);
$provide.value('$window', windowMock);
});
inject(function (_$httpBackend_, _$window_, _$location_, _security_) {
$httpBackend = _$httpBackend_;
$window = _$window_;
$location = _$location_;
security = _security_;
})
$httpBackend
.whenPOST('/api/tokenCheck', {token: "mockBadToken123"})
.respond(400, "Token invalid or undefined");
security.tokenCheck();
expect($location.url).toHaveBeenCalledWith('/login');
expect($window.localStorage.token).toBeUndefined();
});
或者有更高效的方法吗?
编辑: 工厂本身看起来像这样:
angular.module('app.common.security').factory('security', ['$http', '$window', '$location', function ($http, $window, $location) {
var Security = {};
Security.tokenCheck = function () {
if (!$window.localStorage.token) {
$location.url('/login');
return;
}
$http.post('/api/tokenCheck', {token: $window.localStorage.token})
.success(function (data) {
console.log("STUBB: set user data, login status and redirect to panel");
}).error(function (err) {
delete $window.localStorage.token;
$location.url('/login');
});
};
return Security;
}]);
为什么你在考试中没有按照你说的去做?
it("Should call location.url with '/login' and delete token if bad token", function() {
// Need to modify the windowMock.localStorage.token value here somehow
$window.localStorage = { token: "mockBadToken123" };
$location.url = jasmine.createSpy().and.returnValue(true);
$httpBackend
.whenPOST('/api/tokenCheck', {token:"mockBadToken123"})
.respond (400, "Token invalid or undefined");
security.tokenCheck();
$httpBackend.flush();
expect($location.url).toHaveBeenCalledWith('/login');
expect($window.localStorage.token).toBeUndefined();
});