【发布时间】:2014-06-19 19:22:26
【问题描述】:
我对 Javascript 还很陌生,刚刚学习 AngularJS,但我已经让我的大部分测试用例与我发现的一些很好的例子一起工作。不幸的是,我似乎找不到任何东西来帮助我测试我目前的情况。
我正在使用一个模拟服务来测试一个控制器,该服务的方法返回一个承诺。我希望模拟服务返回错误,以便在控制器方法中执行“.catch”块。我可以通过几种方式判断它没有被正确调用:
- 我正在使用 istanbul 进行代码覆盖,它告诉我我没有覆盖“捕获”
- '.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 和 Promise 的方法!谢谢!!!
**更新**
我能够在下面的一些帮助下解决我的问题并发现一些语法错误。以下是解决此问题的方法:
- 我在最后一个测试中的
beforeEach没有正确关闭,实际上包含最后一个测试,导致它无法正确运行(或者可能根本没有)。这就是更改预期条件不会导致错误的原因。 - 我使用下面建议的
reject将beforeEach注入更改为:mockAuthService.login.andReturn($q.reject({data: {message: 'Bad Login!'}}));。 - 当我正确关闭
beforeEach后,我收到一条错误消息,指出 $q 未定义,因此我必须将其添加到inject(function($q)
一旦我纠正了这些问题,promise 就会被正确拒绝,并且错误被控制器中的适当代码捕获。
【问题讨论】:
标签: javascript angularjs unit-testing jasmine promise