Search code examples
angularjsunit-testingjasminehttpbackend

Dynamic $httpBackend response in a unit test


I've created a service to mock my backend and allow paging of content:

angular.module('testedApp')
    .service('mockedResponses', function mockedResponses() {

   var _mediaResponse = {"total":84,"media":[...], groups: {}, keywords: {}};


    return {
        getMediaResponse: function(method, url, data, headers){
            var mediaResponse = angular.copy(_mediaResponse),
                start = headers.skip_current || 0,
                end = headers.limit || 8;

            mediaResponse['media'] = _mediaResponse['media'].splice(start, end);
            return mediaResponse;
        }
    }
});

Test:

'use strict';

describe('Controller: CuratorCtrl', function () {

    // load the controller's module
    beforeEach(module('curationApp'));

    var MainCtrl,
        scope,
        mockedResponses,
        $httpBackend;

    // Initialize the controller and a mock scope
    //Use double underline suffix and prefix to prevent shadowing the outer scope dependencies
    //with the inner scope ones
    beforeEach(inject(function ($controller, $rootScope, _$api_, _Message_,
                                    _tileService_, _$state_, _$httpBackend_, _mockedResponses_) {
        //mock the backend
        $httpBackend = _$httpBackend_
        mockedResponses = _mockedResponses_;
        $httpBackend.whenGET(/customer/).respond(mockedResponses.getCustomerResponse);
        $httpBackend.whenGET(/curation\/media/).respond(mockedResponses.getMediaResponse);

        scope = $rootScope.$new();
        MainCtrl = $controller('CuratorCtrl', {
            $scope: scope,
            $api: _$api_,
            Message: _Message_,
            tileService: _tileService_,
            $state: _$state_,
            $stateParams: {}
        });
    }));


    it('should fetch initial batch of media, and place it on the scope', function(){
        $httpBackend.expectGET('/customer');
        $httpBackend.expectGET('/curation/media');
        scope.$digest();
        $httpBackend.flush();
        expect(scope.groups).toBe(mockedResponses.getMediaResponse().groups);
        expect(scope.hashtags).toBe(mockedResponses.getMediaResponse().keywords);
        expect(scope.media).toBe(mockedResponses.getCustomerResponse());
    });

});

Instead of the expected data(media), I get 'null', on the scope, and an exception is raised by trying to access properties of null.


Solution

  • Ok, Found the solution, according to the docs, the response of the function should be an array of the following stacture [(str)StatusCode, (str, obj)Response, (obj)Headers]

    following code works:

    angular.module('testedApp')
        .service('mockedResponses', function mockedResponses() {
    
       var _mediaResponse = {"total":84,"media":[...], groups: {}, keywords: {}};
    
    
        return {
            getMediaResponse: function(method, url, data, headers){
                var mediaResponse = angular.copy(_mediaResponse),
                    start = headers.skip_current || 0,
                    end = headers.limit || 8;
    
                mediaResponse['media'] = _mediaResponse['media'].splice(start, end);
                return arguments.length ? ['200', mediaResponse, {}] : mediaResponse;
            }
        }
    });