0
votes

I would like to unit test a function in an Angular controller that relies on an asynchronous API call (a promise).

I have a function in a controller that calls a service and sets a $scope variable in the controller based on the result of the service:

$scope.display = 'loading';

$scope.loadData = function() {                           
        ApiService.getSummary().then(                 
            function (response) {                               
                $scope.displayData(response.data);
                $scope.display = 'boxes';                    
            },                                                  
            function (error) {                                  
                $scope.display = 'error';                    
            }                                                   
        );                                                      
    };

I have the following Jasmine unit test

var FunctionFixtures = {
        successFunc: function() {
            var deferred = $q.defer();
            var response = {
                'data': dataVar
            };
            deferred.resolve(response);
            return deferred.promise;
        },
        errorFunc: function() {
            var deferred = $q.defer();
            deferred.reject();
            return deferred.promise;
        }
    };

it('should show the boxes on data load success', function(){
        spyOn(ApiService, 'getSummary').and.callFake(FunctionFixtures.successFunc);
        $scope.loadData();
        expect($scope.display).toBe('boxes');
    });

When I run the test, I get the following error:

Error: Expected 'loading' to be 'boxes'.   

I essentially want to fake the api call and return either a success or a failure and ensure that $scope.display is set to the appropriate string i.e. 'boxes' for success and 'error' failure. Any thoughts on how to do this?

1
Are you missing $scope.loadData() in your test!? - friedi
No, sorry @friedi, I simply left out a the line where I call $scope.loadData() in the test. I've simplified the code here to make it more generic. - Scott Heath

1 Answers

0
votes

It looks like you're missing a call to $rootScope.apply() after the call to loadData() but before the call to expect.

Because of how Angular promises are integrated with the $rootScope, you need to run a digest cycle for resolved promises to call their callbacks, as shown at https://code.angularjs.org/1.2.26/docs/api/ng/service/$q#testing.