javascript 如何在单元测试中通过 jasmine spy 将拒绝/失败承诺返回给角度控制器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24995072/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to return rejected/failure promise to through jasmine spy to an angular controller in a unit test
提问by Nishutosh Sharma
I am using jasmine for testing my angular controllers.
I am catching errors and success in the .then(successCallback, errorCallback)
Although it is working fine on the bases of live functionality but am confused how to write a spy for returning an error as it is always caught in the successCallback()
我正在使用 jasmine 来测试我的角度控制器。我正在捕获错误和成功.then(successCallback, errorCallback)
虽然它在实时功能的基础上运行良好,但我很困惑如何编写一个间谍来返回错误,因为它总是在successCallback()
Following is the controller :-
以下是控制器:-
angular.module('myApp')
.controller('LoginCtrl', function ($scope, $location, loginService, SessionService) {
$scope.errorMessage = '';
$scope.login = function () {
var credentials = {
email: this.email,
password: this.password
};
SessionService.resetSession();
var request = loginService.login(credentials);
request.then(function(promise){ //successfull callback
if (promise['status'] === 200){
//console.log('login');
$location.path('/afterloginpath');
}
},
function(errors){ //fail call back
// console.log(errors);
$location.path('/login');
});
};
});
My test case :-
我的测试用例:-
'use strict';
describe('Controller: LoginCtrl', function () {
// load the controller's module
beforeEach(module('myApp'));
var LoginCtrl, scope, location, login, loginReturn, session;
var credentials = {'email': '[email protected]', 'password': 'admin123'};
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope, $location, _loginService_, _SessionService_) {
scope = $rootScope.$new();
LoginCtrl = $controller('LoginCtrl', {
$scope: scope
});
location = $location;
login = _loginService_;
session = _SessionService_;
scope.errorMessage = '';
spyOn(login, "login").andCallFake(
function(){
return {
then: function(response){
response(loginReturn);
}
}
}
);
spyOn(session, "setName").andCallFake(function(){
return true;
});
}));
it('should go to login when login fail', function () {
loginReturn = function(){
return{
successfullyCallback: {throwError:true},
failCallback: {status: 400, 'data' : {'errors' : [{"type":"invalid_data","target":"email,password"}]}}
}
};
var wrong_creds = {email: '[email protected]', password: 'wrong_password'};
scope.email = wrong_creds.email;
scope.password = wrong_creds.password;
scope.login();
expect(location.path()).toBe("/login");
expect(scope.errorMessage).toBe('username or password combination is invalid');
});
});
回答by ivarni
I find it easier to use actual promises for mocked services as it removes a lot of nested functions and is a lot easier to read.
我发现将实际承诺用于模拟服务更容易,因为它删除了许多嵌套函数并且更容易阅读。
Relevant snippets ($q needs to be injected in beforeEach):
相关片段(在beforeEach中需要注入$q):
deferred = $q.defer();
spyOn(login, 'login').andReturn(deferred.promise);
...
deferred.reject({ ... });
After resolving or rejecting the promise you need to call scope.$digest()
so angular can process it.
在解决或拒绝承诺后,您需要调用scope.$digest()
以便 angular 可以处理它。