我在编写我认为应该是一个简单的单元测试时遇到问题。我有以下控制器:
(function(){ 'use strict';
var LoginController = function($scope, $state, RestService){
var _user = {};
var _message = 'hello';
var _login = function(username, password){
var _success = function(response){
_message = response.success;
_user = response.user;
};
var _error = function(response){
_message = response.success;
};
RestService.postData('/api/login', {username: username, password: password}, _success, _error, {showLoader: true});
};
$scope.model = {
login: _login,
user: _user,
message: _message
};
};
angular.module('danny').controller('LoginController',['$scope', '$state', 'RestService',LoginController]);
})();
以下是规范:
describe('LoginController', function(){
var scope, $httpBackend, controller, restService;
beforeEach(function(){
module('danny');
});
beforeEach(inject(function(_$controller_, _$rootScope_, _$httpBackend_, _RestService_){
$httpBackend = _$httpBackend_;
restService = _RestService_;
scope = _$rootScope_.$new();
controller = _$controller_('LoginController', {
$scope: scope,
RestService: restService
});
}));
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
describe('successfully logging in', function(){
it('should redirect to /blog when authenticated', function(){
var user = {"username":"danny@ravenartmedia.com", "password":"test"};
expect(user.username).toEqual('danny@ravenartmedia.com');
$httpBackend.expectPOST('/api/login', user);
scope.model.login(user);
$httpBackend.flush();
expect(scope.model.user).not.toBe(undefined);
});
});
});
当我运行测试时,业力输出为:
C:\Program Files (x86)\JetBrains\WebStorm 9.0.1\bin\runnerw.exe" C:\nodejs\node.exe c:\Users\danny_000\AppData\Roaming\npm\node_modules\grunt-cli\bin\grunt test
Running "karma:development" (karma) task
INFO [karma]: Karma v0.12.16 server started at http://localhost:9876/
INFO [launcher]: Starting browser PhantomJS
INFO [PhantomJS 1.9.8 (Windows 8)]: Connected on socket SWVDLzehlqv2Z3J0C2Av with id 62852294
PhantomJS 1.9.8 (Windows 8): Executed 0 of 1 SUCCESS (0 secs / 0 secs)
PhantomJS 1.9.8 (Windows 8) LoginController successfully logging in should redirect to /blog when authenticated FAILED
SyntaxError: Unable to parse JSON string
at fromJson (c:/Projects/dannyschreiber/public/vendors/angular/angular.js:1066)
at c:/Projects/dannyschreiber/public/vendors/angular-mocks/angular-mocks.js:1646
at $httpBackend (c:/Projects/dannyschreiber/public/vendors/angular-mocks/angular-mocks.js:1194)
at sendReq (c:/Projects/dannyschreiber/public/vendors/angular/angular.js:9616)
at c:/Projects/dannyschreiber/public/vendors/angular/angular.js:9331
at processQueue (c:/Projects/dannyschreiber/public/vendors/angular/angular.js:13171)
at c:/Projects/dannyschreiber/public/vendors/angular/angular.js:13187
at c:/Projects/dannyschreiber/public/vendors/angular/angular.js:14384
at c:/Projects/dannyschreiber/public/vendors/angular/angular.js:14200
at c:/Projects/dannyschreiber/public/vendors/angular-mocks/angular-mocks.js:1525
at c:/Projects/dannyschreiber/public/src/core/security/login-controller.spec.js:6
Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.3.9/$rootScope/inprog?p0=%24digest
at beginPhase (c:/Projects/dannyschreiber/public/vendors/angular/angular.js:14738)
at c:/Projects/dannyschreiber/public/vendors/angular/angular.js:14180
at c:/Projects/dannyschreiber/public/vendors/angular-mocks/angular-mocks.js:1557
at c:/Projects/dannyschreiber/public/src/core/security/login-controller.spec.js:6
PhantomJS 1.9.8 (Windows 8): Executed 1 of 1 (1 FAILED) (0 secs / 0.031 secs)
PhantomJS 1.9.8 (Windows 8): Executed 1 of 1 (1 FAILED) ERROR (0.028 secs / 0.031 secs)
Warning: Task "karma:development" failed. Use --force to continue.
我最后评论了导致错误的角度模拟线(第1646行),并且由于某种原因,在某处看到,我发送的数据格式不正确。这是现在的错误输出:
Running "karma:development" (karma) task
INFO [karma]: Karma v0.12.16 server started at http://localhost:9876/
INFO [launcher]: Starting browser PhantomJS
INFO [PhantomJS 1.9.8 (Windows 8)]: Connected on socket xGP0gRaa3WEdNVw1DrQm with id 89049214
PhantomJS 1.9.8 (Windows 8): Executed 0 of 1 SUCCESS (0 secs / 0 secs)
PhantomJS 1.9.8 (Windows 8) LoginController successfully logging in should redirect to /blog when authenticated FAILED
Error: Expected POST /api/login with different data
EXPECTED: {"username":"danny@ravenartmedia.com","password":"test"}
GOT: username=danny%40ravenartmedia.com&password=test
at $httpBackend (c:/Projects/dannyschreiber/public/vendors/angular-mocks/angular-mocks.js:1196)
at sendReq (c:/Projects/dannyschreiber/public/vendors/angular/angular.js:9616)
at c:/Projects/dannyschreiber/public/vendors/angular/angular.js:9331
at processQueue (c:/Projects/dannyschreiber/public/vendors/angular/angular.js:13171)
at c:/Projects/dannyschreiber/public/vendors/angular/angular.js:13187
at c:/Projects/dannyschreiber/public/vendors/angular/angular.js:14384
at c:/Projects/dannyschreiber/public/vendors/angular/angular.js:14200
at c:/Projects/dannyschreiber/public/vendors/angular-mocks/angular-mocks.js:1525
at c:/Projects/dannyschreiber/public/src/core/security/login-controller.spec.js:6
Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.3.9/$rootScope/inprog?p0=%24digest
at beginPhase (c:/Projects/dannyschreiber/public/vendors/angular/angular.js:14738)
at c:/Projects/dannyschreiber/public/vendors/angular/angular.js:14180
at c:/Projects/dannyschreiber/public/vendors/angular-mocks/angular-mocks.js:1557
at c:/Projects/dannyschreiber/public/src/core/security/login-controller.spec.js:6
PhantomJS 1.9.8 (Windows 8): Executed 1 of 1 (1 FAILED) (0 secs / 0.032 secs)
PhantomJS 1.9.8 (Windows 8): Executed 1 of 1 (1 FAILED) ERROR (0.029 secs / 0.032 secs)
Warning: Task "karma:development" failed. Use --force to continue.
关键信息是:
Error: Expected POST /api/login with different data
EXPECTED: {"username":"danny@ravenartmedia.com","password":"test"}
GOT: username=danny%40ravenartmedia.com&password=test
为什么我的json被改变了?
这是RestService的postData函数,我在很多项目中都使用过这个函数而没有问题:
var postData = function(url, params, data, successFunction, errorFunction, config) {
if(config && config.hasOwnProperty('showLoader')){
$rootScope.showLoader = config.showLoader;
}
$http({
method: 'POST',
url: url,
params: params,
data: data,
cache: false
})
.success(function(data, status, headers, config) {
$rootScope.showLoader = false;
if (successFunction === undefined) {
_defaultSuccessFunction(data, status, headers, config);
}
else {
successFunction(data, status, headers, config);
}
})
.error(function (data, status, headers, config) {
$rootScope.showLoader = false;
if (status !== 0){
_processError(data, status, headers, config, errorMsg, errorFunction);
}
});
};
修改 我能够在plnkr中挂起所有这些:http://plnkr.co/edit/lJTx0ldR9nEnlYbU5pJd并且测试通过....但完全相同的代码给了我在这篇文章中引用的错误。我正在运行Angular和Angular-Mocks的1.3.9版。
答案 0 :(得分:1)
您的帮助方法定义为function(url, params, data, successFunction, errorFunction, config)
,其中data
是第三个参数。
将此与您的调用进行比较:
RestService.postData('/api/login', null, null, {username: username, password: password}, _success, 'Invalid login, please try again', _error, {showLoader: true});
在这里,您将数据作为第四个参数传递。所以我认为您要删除其中一个null
值。不幸的是,Javscript没有警告错误的参数数量(只是忽略它们)。
编辑:
同时您已编辑了您的问题,但是您postData
的调用可能仍然不正确。
我用你的代码准备了一个小提琴:http://jsfiddle.net/qwteyak3/1/
postData
的第一次调用将数据作为params
参数获取。这告诉$http
将其作为表单数据发送。第二次调用将其传递到data
字段中。 $http
检查数据,找到一个对象,然后将其作为JSON体发送。
在运行小提琴时,Chrome的网络标签向我显示第一次调用http://fiddle.jshell.net/echo/json?password=123&username=test
的请求和第二次调用的http://fiddle.jshell.net/echo/json
(主体数据)。
我希望这会有所帮助。