FrancescoMussi
FrancescoMussi

Reputation: 21630

Karma-Jasmine: How to properly test http calls?

THE SITUATION:

I need to test an http call and make sure it is called properly.

In the app everything is working fine: $scope.language_list properly retrieve the data from the api

But in the test $scope.language_list is undefined. So probably i am not making the test right.

THE CODE:

The function:

$scope.get_language_list = function()
{
    $http.get('http://my_app.org/languageList')
    .success(function(data, status, headers, config) 
    {
        $scope.language_list = data;
        $scope.valid = true;

    })
    .error(function(data, status, headers, config) 
    {
        $scope.valid = false;
    });
}

The test:

describe('Http calls test', function() {

    beforeEach(module('my_app.controllers'));

    beforeEach(inject(function(_$controller_, _$httpBackend_) 
    {
        $scope = {};
        var controller = $controller('MainCtrl', { $scope: $scope });

        $httpBackend = _$httpBackend_;
        $httpBackend.whenGET('http://my_app.org/languageList').respond(200);

    }));

    it('should load default language list', function() 
    {
        $httpBackend.flush();

        console.log($scope.language_list);

        expect($scope.valid).toBe(true);
        expect($scope.language_list).not.toEqual(undefined);
    });


});

THE RESULT:

$scope.valid is tested fine. If I intentionally change its value in the function to see the test fail it does fail, otherwise is properly passed as true.

But $scope.language_list is not working properly, and is passed as undefined. Indeed the error message is: Expected undefined not to equal undefined.

THE QUESTION:

How can i properly test an http call? Why $scope.language_list is undefined? What I am doing wrong in the test?

Thank you very much!

Upvotes: 3

Views: 10531

Answers (1)

Michael Biggs
Michael Biggs

Reputation: 460

You need to provide a mock response object. Currently the "data" parameter in your success function is undefined. To define a response:

beforeEach(inject(function(_$controller_, _$httpBackend_) 
{
    $scope = {};
    var controller = $controller('MainCtrl', { $scope: $scope });

    $httpBackend = _$httpBackend_;

    //Tell the $httpBackend to respond with our mockLangularList array. Or whatever the api actually returns.Array used for example.
    var mockLanguageList = [{key: ''},{key: ''},{key: ''}];
    $httpBackend.whenGET('http://my_app.org/languageList').respond(200, mockLanguageList);

}));

Also, do you every call $scope.get_language_list()?

it('should load default language list', function() 
{
    $scope.get_language_list(); // <-- Make call
    $httpBackend.flush();

    console.log($scope.language_list);

    expect($scope.valid).toBe(true);
    expect($scope.language_list).not.toEqual(undefined);
});

Upvotes: 3

Related Questions