javascript - 由于 Angular 模拟接收到不正确的 json 格式,Jasmine 测试无法进行 $httpbackend 调用

标签 javascript angularjs unit-testing jasmine karma-runner

我在编写我认为应该是简单单元测试的内容时遇到了问题。我有以下 Controller :

 (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);
       });
    });
});

当我运行测试时, karma 输出是这样的:

    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.

我最后注释掉了导致错误的 angular-mocks 行(第 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 版。

最佳答案

您的辅助方法定义为 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 的调用可能仍然不正确。 我已经使用您的代码准备了一个 fiddle :http://jsfiddle.net/qwteyak3/1/

postData 的第一次调用获取数据作为 params 参数。这告诉 $http 将其作为表单数据发送。第二次调用将它传递到 data 字段中。 $http 检查数据,找到一个对象,然后将其作为 JSON 正文发送。

运行 fiddle 时,Chrome 的网络选项卡向我显示了对 http://fiddle.jshell.net/echo/json?password=123&username=test 的第一次调用请求和 http://fiddle.jshell.net/echo/json(正文中有数据)。

希望对您有所帮助。

关于javascript - 由于 Angular 模拟接收到不正确的 json 格式,Jasmine 测试无法进行 $httpbackend 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28012603/

相关文章:

javascript - 根据状态显示按钮而不是文本

javascript - Bootstrap 推荐轮播

javascript - 函数完成后获取事件

ios - Xcode 7.2 : Impossible to run unit tests on iPhone 6s

php - 验证 Symfony 4 单元测试中的命令独白输出

javascript - AngularJS ng-model 将对象转换为字符串

javascript - 如何从按钮检查输入单选 - AngularJS

javascript - 在 AngularJs 中,当我调用函数时无法获取 $scope

javascript - 如何使用 Protractor 获取 Javascript 提示值?

c++ - 使用 Catch2 以全精度打印浮点值