Jasmine testing for function call

1k views Asked by At

I'm new to jasmine testing. How can I test function call in watch function?

Below is my code. I'm confused about usage of spy in jasmine and how can I handle function call inside watcher.

Do I need to pause fetch() inside watch. Please suggest how to improve my testing skills.

var app = angular.module('instantsearch',[]);
    app.controller('instantSearchCtrl',function($scope,$http,$sce){
    $scope.$sce=$sce;
    $scope.$watch('search', function() {
      fetch();
    });
    $scope.search = "How create an array";
    var result = {};
     function fetch() {
        $http.get("https://api.stackexchange.com/2.2/search?page=1&pagesize=10&order=desc&sort=activity&intitle="+$scope.search+"&site=stackoverflow&filter=!4*Zo7ZC5C2H6BJxWq&key=DIoPmtUvEkXKjWdZB*d1nw((")
        .then(function(response) {
           $scope.items = response.data.items;
           $scope.answers={};
            angular.forEach($scope.items, function(value, key) {
                var ques = value.question_id;
                $http.get("https://api.stackexchange.com/2.2/questions/"+value.question_id+"/answers?page=1&pagesize=10&order=desc&sort=activity&intitle="+$scope.search+"&site=stackoverflow&filter=!9YdnSMKKT&key=DIoPmtUvEkXKjWdZB*d1nw((").then(function(response2) {                                                                                                                                                   
                    $scope.answers[ques]=response2.data.items;  
                    //console.log(JSON.stringify($scope.answers));
                });
            });
        });                                                                                                                                                                                                                                             
     }
});

my test case:

describe('instantSearchCtrl', function() {
  beforeEach(module('instantsearch'));

 var $scope, ctrl;

 beforeEach( inject(function($rootScope, $controller) {
      // create a scope object for us to use.
      $scope = $rootScope.$new();


      ctrl = $controller('instantSearchCtrl', {
        $scope: $scope
      });

  }));

      /*var $scope = {};
      var controller = $controller('instantSearchCtrl', { $scope: $scope });
       expect($scope.search).toEqual('How create an array');
      //expect($scope.strength).toEqual('strong');*/
 it('should update baz when bar is changed', function (){

    //$apply the change to trigger the $watch.
    $scope.$apply();
    //fetch().toHaveBeenCalled();

    fetch();
  it(" http ", function(){
  //scope = $rootScope.$new();
        var httpBackend;
            httpBackend = $httpBackend;
            httpBackend.when("GET", "https://api.stackexchange.com/2.2/search?page=1&pagesize=10&order=desc&sort=activity&intitle="+$scope.search+"&site=stackoverflow&filter=!4*Zo7ZC5C2H6BJxWq&key=DIoPmtUvEkXKjWdZB*d1nw((").respond([{}, {}, {}]);
    });
});
});
1

There are 1 answers

0
rave On

First you should trigger the watch. For that you should change search value and after that manually run: $scope.$digest() or $scope.$apply()

In order to fully test the fetch function you should also mock the response to the second request (or the mock for all the second level requests if you want to test the iteration).

After that you should add some expect statements. For the controller code they should be:

expect($scope.items).toEqual(mockResponseToFirstRequest);
expect($scope.answers).toEqual(mockResponseCombinedForSecondLevelRequests);

As for using the spy in karma-jasmine tests, those limit the amount of the code tested. A plausible use for spy in this case is to replace the httpBackend.when with spyOn($http, 'get').and.callFake(function () {})

Here is the documentation for using spies https://jasmine.github.io/2.0/introduction.html#section-Spies