Oam Psy
Oam Psy

Reputation: 8663

Angular unit test .catch block

I have a controller and service for which I have written some unit test. The service perform http request, controller has .then and .catch block. I can test .then block no problem, but how to test .catch?

Controller:

$scope.performPost = function (action) {

    $scope.shoppingCart = function() {
        $scope.loading = true;
        $scope.acText = '';

        myService.postAction('cart', $scope.myData)
            .then(function(data) {
                $timeout(function(){
                    $scope.loading = false;
                    $scope.tick = true;
                }, 1500);
            })
            .catch(function() {
                $scope.errorException();
            });
    };

    switch(action) {
        case "viewShoppingCart":
            $scope.shoppingCart();
            break;
        case "updateProfile":
            $scope.updateUserDetails();
            break;
    }
};

Test for .then:

describe("MyController Tests", function() {

    var scope;
    var ctrl;

    var customer = {
            "accountId" : "12345678901",
            "firstName" : "Joe",
            "lastName" : "Bloggs",
    };

    var unlockRespone = {};

    beforeEach(inject(function($rootScope, $controller, myService, _$q_, $httpBackend, $timeout) {
        scope = $rootScope.$new();
        rootScope = $rootScope;
        mockMyService = myService;
        pingUrl = "http://server:80/ping";
        httpBackend = $httpBackend;
        timeout = $timeout;    

        var unlockDeferred = _$q_.defer();
        unlockDeferred.resolve(unlockRespone);
        spyOn(mockMyService, 'postAction').and.returnValue(unlockDeferred.promise);

        spyOn(rootScope, '$broadcast').and.callThrough();

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

        spyOn(scope, 'performPost').and.callThrough();
    }));   

    it("Should call the viewShoppingCart function", function() {
        httpBackend.expectGET(pingUrl).respond({ status: "OK" });
        scope.performPost('viewShoppingCart');
        timeout.flush(4000);
        expect(scope.loading).toBeFalsy();
        expect(scope.tick).toBeTruthy();   
    });
});

Upvotes: 0

Views: 5853

Answers (2)

user3498393
user3498393

Reputation: 84

describe("MyController Tests", function() {

    var scope;
    var ctrl;
    var $q;

    var customer = {
            "accountId" : "12345678901",
            "firstName" : "Joe",
            "lastName" : "Bloggs",
    };

    var response = {};

    beforeEach(inject(function($rootScope, $controller, myService, _$q_, $httpBackend, $timeout) {
        scope = $rootScope.$new();
        rootScope = $rootScope;
        mockMyService = myService;
        pingUrl = "http://server:80/ping";
        httpBackend = $httpBackend;
        timeout = $timeout;   
        $q = _$q_;




        spyOn(rootScope, '$broadcast').and.callThrough();

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

        spyOn(scope, 'performPost').and.callThrough();
    }));   

    it("calls then", function() {
        var deferred = $q.defer();
        deferred.resolve(response);

        spyOn(mockMyService, 'postAction').and.returnValue(deferred.promise);

        // test code for then   
    });

    it("calls catch", function() {
        var deferred = $q.defer();
        deferred.reject(response);

        spyOn(mockMyService, 'postAction').and.returnValue(deferred.promise);

        // test code for catch   
    });
});

Upvotes: 2

Raulucco
Raulucco

Reputation: 3426

You can pass 500 or other error status, to the respond method of $httpBackend as the first argument.

  it("Should call errorException", function() {
        spyOn(scope, 'errorException');
        httpBackend.expectPOST('shopping-cart-url').respond(500, '');
        scope.performPost('viewShoppingCart');
        httpBackend.flush();
        expect(scope.errorException).toHaveBeenCalled();
    });

Upvotes: 1

Related Questions