由于角度模拟接收到错误的json格式,Jasmine测试无法进行$ httpbackend调用

时间:2015-01-18 17:24:31

标签: javascript angularjs unit-testing jasmine karma-runner

我在编写我认为应该是一个简单的单元测试时遇到问题。我有以下控制器:

 (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版。

1 个答案:

答案 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(主体数据)。

我希望这会有所帮助。