[英]How Can I Test a .catch Promise Return in AngularJS using Jasmine?
我对Javascript很新,只是学习AngularJS,但我已经把大部分测试用例都用到了我发现的一些很好的例子。 不幸的是,我似乎无法找到任何东西来帮助我测试我目前的情况。
我正在使用模拟服务测试Controller,其方法返回一个promise。 我希望模拟的服务返回一个错误,以便在控制器方法中执行'.catch'块。 我可以说它在几个方面没有被正确调用:
正在测试的控制器,特别需要在$ scope.login中测试'.catch':
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)
一旦我纠正了这些问题,承诺就被正确拒绝,错误被控制器中的相应代码捕获。
在运行测试之前或同时,模拟部分环境,如下所示:
var originalAuthLogin = Auth.login;
Auth.login = function() {
return Promise.reject({data: {message: 'Error message'}});
};
测试结束后恢复环境:
Auth.login = originalAuthLogin;
这会立即调用您尝试测试的代码的.catch()
块。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.