Karma-Jasmine: How to properly test http calls?

10,167

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);
});
Share:
10,167
FrancescoMussi
Author by

FrancescoMussi

Full-stack developer based in Riga, Latvia. Hope Socrates is proud of my Socratic badge on StackOverflow.

Updated on June 04, 2022

Comments

  • FrancescoMussi
    FrancescoMussi almost 2 years

    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!

  • FrancescoMussi
    FrancescoMussi over 8 years
    Thank you for reply. I don't understand one thing: in this way $scope.language_list will contain whatever value i pass previously to mockLanguageList. If it is an empty array will be an empty array. If mockLanguageList = 'hello', then $scope.language_list will contain 'hello'. So how can i know the http call has been called properly? Should not contain the real data from the api?
  • Michael Biggs
    Michael Biggs over 8 years
    @johnnyfittizio mockLanguageList should be set to whatever the api is supposed to return. With front end unit tests you don't want to actually call the api. This could introduce major complexity (Authentication) Testing the actual api is would be done from your server side code test suite. We only want to test front end code here. You are verifying the correct api is called when you specify the whenGET('...').