AngularJS 使用返回承诺的服务测试控制器
AngularJS testing controller using a service returning a promise
我正在为我的组件编写单元测试。
我知道这个问题在研究了很多之前和之后都得到了回答,感觉测试依赖于服务的东西很麻烦或者需要脏活。
对我来说,以下感觉很脏,如果这是要走的路,我会征求你的意见:)
这是我的控制器
function Login($location, AuthService) {
var vm = this;
vm.error = "";
vm.login = login;
//////////
function login(credentials) {
AuthService.login(credentials)
.then(function(user) {
$location.path("/menu");
})
.catch(function(q) {
vm.error = q.data.error;
});
}
}
考试准备,我假 $location
和我的 AuthService
:
beforeEach(inject(function($q) {
location = {
path: function(q) { path = q; }
};
AuthService = {
login: function(credentials) {
deferred = $q.defer();
if (credentials)
deferred.resolve();
else
deferred.reject({ data: {error: "My Error"} });
return deferred.promise;
}
};
}));
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
Login = $controller('Login', {
$location: location,
AuthService: AuthService
});
}));
和测试:
describe("(login)", function() {
it('should redirect on successful login', function() {
Login.login(true);
scope.$root.$digest();
expect(path).toBe("/menu");
});
it('should show error on failed login', function() {
Login.login(false);
scope.$root.$digest();
expect(Login.error).toBe("My Error");
});
});
一切正常,但使用全局变量和事后检查感觉很脏。
我感谢每一个意见和每一个更清洁的方法:)
我认为这会是一种更简洁的方法
beforeEach(inject(function(_$rootScope_, $controller, _AuthService_, _$location_, _$q_) {
$rootScope = _$rootScope_;
AuthService = _AuthService_;
$location = _$location_;
$q = _$q_;
spyOn($location, 'path').and.stub();
var scope = $rootScope.$new();
Login = $controller('Login', { $scope: scope });
}));
describe("(login)", function() {
it('should redirect on successful login', function() {
spyOn(AuthService, 'login').and.returnValue($q.resolve());
Login.login(true);
$rootScope.$digest();
expect($location.path).toHaveBeenCalledWith('/menu');
});
it('should show error on failed login', function() {
spyOn(AuthService, 'login').and.returnValue($q.reject({
data: {error: "My Error"}
}));
Login.login(false);
$rootScope.$digest();
expect(Login.error).toBe("My Error");
});
});
path
全局看起来不太好(即使它是 describe
范围内的局部变量),你不必为他们做间谍的工作。
我正在为我的组件编写单元测试。
我知道这个问题在研究了很多之前和之后都得到了回答,感觉测试依赖于服务的东西很麻烦或者需要脏活。
对我来说,以下感觉很脏,如果这是要走的路,我会征求你的意见:)
这是我的控制器
function Login($location, AuthService) {
var vm = this;
vm.error = "";
vm.login = login;
//////////
function login(credentials) {
AuthService.login(credentials)
.then(function(user) {
$location.path("/menu");
})
.catch(function(q) {
vm.error = q.data.error;
});
}
}
考试准备,我假 $location
和我的 AuthService
:
beforeEach(inject(function($q) {
location = {
path: function(q) { path = q; }
};
AuthService = {
login: function(credentials) {
deferred = $q.defer();
if (credentials)
deferred.resolve();
else
deferred.reject({ data: {error: "My Error"} });
return deferred.promise;
}
};
}));
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
Login = $controller('Login', {
$location: location,
AuthService: AuthService
});
}));
和测试:
describe("(login)", function() {
it('should redirect on successful login', function() {
Login.login(true);
scope.$root.$digest();
expect(path).toBe("/menu");
});
it('should show error on failed login', function() {
Login.login(false);
scope.$root.$digest();
expect(Login.error).toBe("My Error");
});
});
一切正常,但使用全局变量和事后检查感觉很脏。
我感谢每一个意见和每一个更清洁的方法:)
我认为这会是一种更简洁的方法
beforeEach(inject(function(_$rootScope_, $controller, _AuthService_, _$location_, _$q_) {
$rootScope = _$rootScope_;
AuthService = _AuthService_;
$location = _$location_;
$q = _$q_;
spyOn($location, 'path').and.stub();
var scope = $rootScope.$new();
Login = $controller('Login', { $scope: scope });
}));
describe("(login)", function() {
it('should redirect on successful login', function() {
spyOn(AuthService, 'login').and.returnValue($q.resolve());
Login.login(true);
$rootScope.$digest();
expect($location.path).toHaveBeenCalledWith('/menu');
});
it('should show error on failed login', function() {
spyOn(AuthService, 'login').and.returnValue($q.reject({
data: {error: "My Error"}
}));
Login.login(false);
$rootScope.$digest();
expect(Login.error).toBe("My Error");
});
});
path
全局看起来不太好(即使它是 describe
范围内的局部变量),你不必为他们做间谍的工作。