我对Javascript很新,只是学习AngularJS,但我已经将大部分测试用例与我发现的一些很好的例子一起使用。不幸的是,我似乎无法找到任何可以帮助我测试当前案例的内容。
我使用模拟服务测试Controller,其方法返回一个promise。我希望模拟的服务返回错误,以便执行' .catch'阻塞在控制器方法中。我可以说它没有通过几种方式正确调用:
被测控制器,具体需要测试' .catch'在$ scope.login中:
login.js
'use strict';
angular.module('ibcwebDashApp')
.controller('LoginCtrl', function ($scope, Auth, $location) {
$scope.user = {};
$scope.errors = {};
$scope.login = function(form) {
$scope.submitted = true;
if(form.$valid) {
Auth.login({
email: $scope.user.email,
password: $scope.user.password
})
.then( function() {
// Logged in, redirect to home
$location.path('/');
})
.catch( function(err) {
err = err.data;
$scope.errors.other = err.message;
});
}
};
});
我试图模仿的服务和方法:
Auth.login
'use strict';
angular.module('ibcwebDashApp')
.factory('Auth', function Auth($location, $rootScope, Session, User, $cookieStore) {
// Get currentUser from cookie
$rootScope.currentUser = $cookieStore.get('user') || null;
$cookieStore.remove('user');
return {
/**
* Authenticate user
*
* @param {Object} user - login info
* @param {Function} callback - optional
* @return {Promise}
*/
login: function(user, callback) {
var cb = callback || angular.noop;
return Session.save({
email: user.email,
password: user.password
}, function(user) {
$rootScope.currentUser = user;
return cb();
}, function(err) {
return cb(err);
}).$promise;
},
最后,我的测试文件。有趣的是,所有测试都在通过,但是期望'在最后一次测试中可以改为几乎任何东西而且它仍然通过。前两个测试似乎按预期运行,但最后一个测试是我试图通过从模拟Auth服务抛出错误来执行catch块:
login.unit.js
'use strict';
describe('Controller: LoginCtrl', function () {
var $scope, $location, loginCtrl, mockAuthService;
beforeEach(function() {
mockAuthService = jasmine.createSpyObj('Auth', ['login']);
module('ibcwebDashApp');
module(function($provide) {
$provide.value('Auth', mockAuthService);
});
inject(function($rootScope, $controller, $q, _$location_) {
//create an empty scope
$scope = $rootScope.$new();
$location = _$location_;
//declare the controller and inject our empty scope
loginCtrl = $controller('LoginCtrl', {$scope: $scope, Auth: mockAuthService});
});
});
describe('successful login', function() {
beforeEach(function() {
inject(function($q) {
mockAuthService.login.andReturn($q.when());
});
});
it('should call auth.login with the scope email and password when form is valid', function() {
//given
$scope.form = {};
$scope.form.$valid = true;
$scope.user.email = 'user@test.com';
$scope.user.password = 'password123';
//when
$scope.login($scope.form);
//then
expect($scope.submitted).toBe(true);
expect(mockAuthService.login).toHaveBeenCalledWith({email:'user@test.com', password:'password123'});
$scope.$apply(); //force return of auth.login promise
expect($location.path()).toBe('/');
});
it('should not call auth.login if form is invalid', function() {
//given
$scope.form = {};
$scope.form.$valid = false;
//when
$scope.login($scope.form);
expect(mockAuthService.login).not.toHaveBeenCalled();
});
});
describe('unsuccessful login', function() {
beforeEach(function () {
inject(function () {
mockAuthService.login.andReturn($q.when(new Error('Bad Login!')));
});
it('should set errors.other to the returned auth error message', function() {
//given
$scope.form = {};
$scope.form.$valid = true;
//when
$scope.login($scope.form);
$scope.$apply();
//then
expect($scope.errors.other).toEqual('Bad Login!');
});
});
});
});
我为发布这么多代码而道歉,但我想提供尽可能多的上下文。我非常感谢任何可以帮助我的人,因为我学习了单元测试Angular和承诺的方法!感谢!!!
**更新**
我能够通过下面的帮助解决我的问题并发现一些语法错误。以下是解决这个问题的原因:
beforeEach
没有正确关闭,实际上包含了最后一次测试,导致它无法正常运行(或者可能根本没有运行)。这就是改变期望条件导致没有错误的原因。beforeEach
将mockAuthService.login.andReturn($q.reject({data: {message: 'Bad Login!'}}));
注入更改为:reject
。beforeEach
,我收到一条错误消息,指出$ q未定义,因此我必须将其添加到inject(function($q)
我纠正了这些问题后,承诺被正确拒绝,错误被控制器中的相应代码捕获。
答案 0 :(得分:9)
在运行测试之前或期间,模拟出部分环境:
var originalAuthLogin = Auth.login;
Auth.login = function() {
return Promise.reject({data: {message: 'Error message'}});
};
测试结束后恢复环境:
Auth.login = originalAuthLogin;
这会立即调用您尝试测试的代码的.catch()
块。