无法在控制器中测试.success功能

时间:2016-01-27 17:16:17

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

我有一个执行HTTP POST的简单控制器和服务。控制器有.success和.error回调,我试图编写一些单元测试:

致电btnClick:

<button ng-click="btnClick('cart')">Click</button>

控制器:

app.controller('MyController', function($scope, myService, $timeout) {

    $scope.btnClick = function (action) {

        $scope.postData = {"ID": $scope.myId, "user": $scope.myUser};

        $scope.cartRequest = function() {
            $scope.disabled = true;
            $scope.myText = '';

            myService.postAction('cart', $scope.postData)
                .success(function (data, status, headers, config) {
                    $timeout(function(){
                        $scope.disabled = false;
                        $scope.myText = 'Inside Timeout';

                        $timeout(function(){
                            $scope.hideBtn = true;
                        }, 1400);

                    }, 1500);                    
                })                    
                .error(function (data, status, headers, config) {
                   $scope.cartError();
                });
        };

        switch(action) {
            case "cart":
                $scope.cartRequest();
                break;
        }
    };

为MyService:

 app.factory('MyService', function ($http) {

    return {
        postAction: function(uri, postData) {
            return $http({
                method: 'POST',
                url: '/cartInfo/' + uri,
                data: postData,
                headers: {'Content-Type': 'application/json'}
            });
        }
    };
});
});

我的测试:

describe('Cart API: can get cart details', function () {
    var myService, httpBackend;

    var customerInfo = {
            "accountId" : "12345678901",
            "userName" : "MyTestUser",
            "firstName" : "Joe",
            "lastName" : "Bloggs"
    };

    beforeEach(inject(function($rootScope, $controller) {
        scope = $rootScope.$new();        

        ctrl = $controller('MyController', {$scope:scope});

        spyOn(scope, 'btnClick').and.callThrough();

        inject(function ($httpBackend, _MyService_, $timeout) {
            MyService = _MyService_;
            httpBackend = $httpBackend;
            timeout = $timeout;
        });
    }));

    it('should check if a user is already logged in', function () {    
        scope.customer = customerInfo;
        scope.btnClick('cart');

        var returnData = {};
        var result = {};
        var mockData = { "accountId" : scope.customer.accountId, "userName" : scope.customer.userName};

        httpBackend.expectPOST('/cartInfo/cart', mockData, function () {
            return {
                'Content-Type': 'application/json'
            };
        }).respond(200, returnData);        



        myService.postAction('unlock', mockData).success(function (response) {
            console.log("hello");
            timeout.flush(1501);
            scope.$apply();
            expect(scope.disabled).toBeFalsy();
            expect(scope.myText).toEqual('Inside Timeout');
        });

    });
});

似乎我的测试中的.success块永远不会像2所期望的那样被调用:

expect(scope.disabled).toBeFalsy();
expect(scope.myText).toEqual('Inside Timeout');

似乎没有跑。

1 个答案:

答案 0 :(得分:1)

规范中的承诺假设规格应为asynchronous。但Angular的承诺必须经过测试synchronously

    myService.postAction('unlock', mockData);
    $rootScope.$digest();
    timeout.flush();
    // can be omitted if scope watchers don't affect the spec
    // scope.$apply();
    expect(scope.disabled).toBeFalsy();
    expect(scope.myText).toEqual('Inside Timeout');