Search code examples
javascriptangularjsjasminekarma-jasmineangular-mock

angular resource promise catch, jasmine toThrow()


I have some code in an angular controller:

user is an angular $resource which returns a promise when the get method is called.

$scope.credentials = {
        username:"",
        password:"",
        rememberMe:false
    };

var currentUser  = {};

$scope.login = function(callback){
        user.get($scope.credentials)
            .$promise
            .then(function(user){
                $scope.currentUser = user;
                return cb ? cb(user) : user;
            })
            .catch(function(res){
                throw "LoginError";
            });

};

I'm trying to test whether it throws the error or not with jasmine like so:

expect(function(){
  scope.login();
}).toThrow();

But this error is thrown:

Expected function to throw an exception.

I have tested the acceptance of the promise, which works as expected, but i'm assuming theres some asynchronous aspect that i'm not able to deal with.

I also tried calling passing in and calling done() but that didn't work either.

edit:

I am mocking out my backend like so:

beforeEach(inject(function($rootScope,$controller,_$httpBackend_){



            $httpBackend = _$httpBackend_;
            successCallback = jasmine.createSpy();
            errorCallback = jasmine.createSpy();


            scope = $rootScope.$new();
            controller = $controller('LoginController',{
                '$scope':scope
            });

        }));

afterEach(function(){
            $httpBackend.verifyNoOutstandingExpectation();
            $httpBackend.verifyNoOutstandingRequest();
        });

Note that my other tests do work, I have tried other scenarios where the server returns 200 and a user and everything works. I am specifically testing whether $scope.login() throws an error when it receives a server error.


Solution

  • You need to setup your $httpBackend to mock the response of your resource. You then need to flush these results so you have control over when they resolve.

    I put together a quick example of your scenario for you on plunker.

    http://plnkr.co/edit/lnWaS1lyJja56Zh1STyl?p=preview

    The relevant spec file. http://embed.plnkr.co/lnWaS1lyJja56Zh1STyl/appSpec.js

    Snippet at a glance:

    $httpBackend.expectGET('/api/index.php/user')
                    .respond(500, 'error');
    //Initiate request by calling your api/resource
    $httpBackend.flush();