jjt143
jjt143

Reputation: 71

Testing $http.get() requests in angular

I'm trying to write jasmine tests for http.get() requests that are made as part of the instantiation of my controller:

e.g

angular.module('dashboard').controller('DashboardCtrl', ['$scope', '$rootScope', '$http', function($scope, $rootScope, $http) {

$scope.module_names = [
    [0, 'WorkforceMap', null, null],
    [10, 'Engagement SentiMap', 'Sentiment', 'engagement'],
    [11, 'Change SentiMap', 'Sentiment', 'change'],
];

$http.get('api/info', {cache: true}).success(function(data) {
    $rootScope.dash_info = data;

    var comp = $rootScope.components = [];
    for(var i = 0; i < scope.module_names.length; i++) {
        var mod = scope.module_names[i];
        if(mod[0] in data.modules)
            comp.push([mod[1], mod[3]]);
        else
            del_module(mod[2], mod[3]);
    }
});

$http.get('api/population_data', {cache: true}).success(function(data) {
    $rootScope.population_data = data;
});

And a few more http requests as well.

I'm trying to write unit tests using httpBackend for the first api call 'api/info', and have been struggling.

describe("DashboardCtrl Tests", function(){

beforeEach(module('dashboard'));

var scope;
var $httpBackend;
var controller;

beforeEach(inject(function(_$controller_, _$httpBackend_, $rootScope, $injector){

    scope = $rootScope.$new();
    controller = _$controller_('DashboardCtrl', {$scope: scope});

    $httpBackend = _$httpBackend_;
    $httpBackend.expectGET('/api/info').respond({'short': 'hi'});
}));

describe('$http.get(api/info)', function(){

    it(' receives data from dashboard/:profile_id/api/info', function(){

        $httpBackend.expectGET('api/info');
        $httpBackend.flush();


    });
});
});

I think the reason i've been struggling is that i haven't been able to find out how to single out one http.get request, since all requests are executed when the controller is instantiated.

My most recent error is "ReferenceError: Can't find variable: scope"

I'll keep digging around, but if anyone has seen something like this before, I would greatly appreciate some guidance!

Thanks

Upvotes: 2

Views: 2370

Answers (1)

Boris Charpentier
Boris Charpentier

Reputation: 3543

What I do in that case is isolate call in methods, you can at minimum wrap all of this in a $scope.init function and test it.

A nicer way would be to cut that on smaller function, and the best way, to have a service wich return $http promise in those smaller function.

An exemple of init :

angular.module('dashboard').controller('DashboardCtrl', ['$scope', '$rootScope', '$http', function($scope, $rootScope, $http) {

$scope.init = function (){

    $scope.module_names = [
        [0, 'WorkforceMap', null, null],
        [10, 'Engagement SentiMap', 'Sentiment', 'engagement'],
        [11, 'Change SentiMap', 'Sentiment', 'change'],
    ];

    $scope.info();

    $http.get('api/population_data', {cache: true}).success(function(data) {
       $rootScope.population_data = data;
    });

};

$scope.info = function (){
    $http.get('api/info', {cache: true}).success(function(data) {
    $rootScope.dash_info = data;

    var comp = $rootScope.components = [];
    for(var i = 0; i < scope.module_names.length; i++) {
        var mod = scope.module_names[i];
        if(mod[0] in data.modules)
            comp.push([mod[1], mod[3]]);
        else
            del_module(mod[2], mod[3]);
    }
    });
};    

$scope.init();

And in test :

describe('$http.get(api/info)', function(){

it(' receives data from dashboard/:profile_id/api/info', function(){

    $httpBackend.expectGET('api/info').respond({'title':'test'});
    scope.info();
    $httpBackend.flush();
    $rootScope.$digest();

    expect($rootScope.dash_info).toEqual({'title':'test'});


});
});

Upvotes: 0

Related Questions