angularjs 使用 jasmine 进行测试 - $httpBackend 没有给我正确的行为
angularjs testing with jasmine - $httpBackend not giving me the right behavior
这是我的控制器:
rcCtrls.controller('LoginController', [
'$scope',
'AuthService',
function($scope, AuthService)
{
console.log('LoginController');
$scope.credantials = {
email: '',
password: '',
remember: false
}
$scope.login = function(credantials)
{
console.log('before login');
AuthService.login(credantials.email, credantials.password, credantials.remember || false).success(function(response) {
console.log('login successful');
console.log(response);
location.reload();
}).error(function() {
console.log('failed to login');
});
};
}]);
这是我的 AuthService:
rcServices.factory('AuthService', [
'$http',
function($http)
{
return {
login: function(email, password, remember) {
console.log('Auth Service Login');
return $http.post('/auth/login', {email: email, password: password, remember: remember});
},
logout: function() {
return $http.post('/auth/logout');
}
};
}]);
这是我的规格:
describe('Controller: LoginController', function() {
// We initiate the app moudle mock
beforeEach(module('app')); // alias for angular.mock.module('app')
beforeEach(inject(function($controller, $rootScope, AuthService, $httpBackend){
this.$httpBackend = $httpBackend;
this.scope = $rootScope.$new();
$controller('LoginController', {
$scope: this.scope,
AuthService: AuthService
});
}));
describe("checking credantials at the begining", function() {
it("should be initiated", function() {
expect(this.scope.credantials).toEqual({ email: '', password: '', remember: false });
});
});
describe("successfully logged in", function() {
it("should redirect to home", function() {
this.scope.credantials = { email: 'test@mail.com', password: '123', remember: false };
this.$httpBackend.expectPOST('/auth/login', this.scope.credantials).respond(200, {test: 'test'});
this.scope.login(this.scope.credantials);
console.log(this);
this.$httpBackend.flush();
expect(this.scope).toBeDefined();
});
});
});
似乎 $httpBackend 没有做它应该做的事情。
我确实得到了所有控制台日志,直到我的服务使用 $http post 请求的那一刻,然后它停止了。
仅供参考,我的控制器在应用程序本身上正常工作! post 正在发生并且响应正在正确返回。
但是测试并没有...
我遇到错误:
Error: No pending request to flush !
评论它没有帮助。
编辑:
问题出在我的 angular-mock.js 版本上....真可悲。
在您的服务中您调用:
location.reload();
这可能会干扰 jasmine 并导致不可预测的行为。这个调用有什么作用,你需要它吗?如果你把它注释掉,你的测试会发生什么?
如果你真的需要进行那个调用,你应该使用AngularJS内置的$location服务并模拟它,这样你就可以保持行为但不破坏茉莉花正在处理中。
===========
更新:
此外,您使用 this.httpBackend 有点奇怪,而通常情况下您会完全覆盖引用 - 不是将其作为 this 的属性存储,而是作为测试的全局变量存储。我怀疑您已经在应用程序的其他地方调用了 flush 并且引用未正确重置。你有任何其他调用 flush 的测试吗?
http://plnkr.co/edit/jBewavvO1n8NBa6WGFja
我在这个 plunkr 中进行了工作测试,它按原样通过了你的代码。除了我注释掉的 location.reload() 行之外,它并没有破坏测试,尽管这个测试运行器与它在 plunkr 中的有点不同,而且情况并非总是如此。你真的不应该在测试中调用它。
这是我的控制器:
rcCtrls.controller('LoginController', [
'$scope',
'AuthService',
function($scope, AuthService)
{
console.log('LoginController');
$scope.credantials = {
email: '',
password: '',
remember: false
}
$scope.login = function(credantials)
{
console.log('before login');
AuthService.login(credantials.email, credantials.password, credantials.remember || false).success(function(response) {
console.log('login successful');
console.log(response);
location.reload();
}).error(function() {
console.log('failed to login');
});
};
}]);
这是我的 AuthService:
rcServices.factory('AuthService', [
'$http',
function($http)
{
return {
login: function(email, password, remember) {
console.log('Auth Service Login');
return $http.post('/auth/login', {email: email, password: password, remember: remember});
},
logout: function() {
return $http.post('/auth/logout');
}
};
}]);
这是我的规格:
describe('Controller: LoginController', function() {
// We initiate the app moudle mock
beforeEach(module('app')); // alias for angular.mock.module('app')
beforeEach(inject(function($controller, $rootScope, AuthService, $httpBackend){
this.$httpBackend = $httpBackend;
this.scope = $rootScope.$new();
$controller('LoginController', {
$scope: this.scope,
AuthService: AuthService
});
}));
describe("checking credantials at the begining", function() {
it("should be initiated", function() {
expect(this.scope.credantials).toEqual({ email: '', password: '', remember: false });
});
});
describe("successfully logged in", function() {
it("should redirect to home", function() {
this.scope.credantials = { email: 'test@mail.com', password: '123', remember: false };
this.$httpBackend.expectPOST('/auth/login', this.scope.credantials).respond(200, {test: 'test'});
this.scope.login(this.scope.credantials);
console.log(this);
this.$httpBackend.flush();
expect(this.scope).toBeDefined();
});
});
});
似乎 $httpBackend 没有做它应该做的事情。
我确实得到了所有控制台日志,直到我的服务使用 $http post 请求的那一刻,然后它停止了。
仅供参考,我的控制器在应用程序本身上正常工作! post 正在发生并且响应正在正确返回。
但是测试并没有...
我遇到错误:
Error: No pending request to flush !
评论它没有帮助。
编辑:
问题出在我的 angular-mock.js 版本上....真可悲。
在您的服务中您调用:
location.reload();
这可能会干扰 jasmine 并导致不可预测的行为。这个调用有什么作用,你需要它吗?如果你把它注释掉,你的测试会发生什么?
如果你真的需要进行那个调用,你应该使用AngularJS内置的$location服务并模拟它,这样你就可以保持行为但不破坏茉莉花正在处理中。
===========
更新:
此外,您使用 this.httpBackend 有点奇怪,而通常情况下您会完全覆盖引用 - 不是将其作为 this 的属性存储,而是作为测试的全局变量存储。我怀疑您已经在应用程序的其他地方调用了 flush 并且引用未正确重置。你有任何其他调用 flush 的测试吗?
http://plnkr.co/edit/jBewavvO1n8NBa6WGFja
我在这个 plunkr 中进行了工作测试,它按原样通过了你的代码。除了我注释掉的 location.reload() 行之外,它并没有破坏测试,尽管这个测试运行器与它在 plunkr 中的有点不同,而且情况并非总是如此。你真的不应该在测试中调用它。