TypeError: Cannot read property 'then' of undefined angularjs-grunt test

22,280

If you only need to find out whether getFilterData is called or not, try returning a fake promise by faking the function:

With jasmine 1.3, we could use andCallFake:

it('should call getFilterData() in bindFilters()', function () {
    spyOn(scope, 'getFilterData').andCallFake(function(){//replace with a fake function
        var deferred = $q.defer(); //assume that you already inject $q service in beforeEach and save it as a variable.
        return deferred.promise; //returns a fake promise
    });
    scope.bindFilters();
    expect(scope.getFilterData).toHaveBeenCalled();
  });

With jasmine 2.0, we could use and.callFake instead.

Another solution is to use andReturnValue and $q.when():

it('should call getFilterData() in bindFilters()', function () {
        spyOn(scope, 'getFilterData').andReturnValue($q.when());
        scope.bindFilters();
        expect(scope.getFilterData).toHaveBeenCalled();
      });

With jasmine 2.0, we could use and.returnValue instead.

Share:
22,280
Chandu
Author by

Chandu

I'm a developer

Updated on July 09, 2022

Comments

  • Chandu
    Chandu almost 2 years

    I'm using $q service to make an async calls. I can't resolve 'then' and 'defer' in unit tests using karma.

    The below is my controller code.

    scope.filterUrls = [{url:'page1'}, {url: 'page2'}, {url:'page-error'}];
    
    scope.bindFilters = function () {
    angular.forEach(scope.filterUrls, function (data) {
        scope.getFilterData(data.url, '').then(function (result) {
          if (data.url === 'page1') {
            scope.moduleData.index = result.data;
          } else if (data.url === 'page2') {
            scope.moduleData.page2 = result.data;
          } 
         });
      });
    }
    
    scope.getFilterData = function (filterUrls, params) {
      // $q service object
      var deferred = q.defer();
    
      // regular ajax request
      http({
        method: 'GET',
        url: app.api.root + filterUrls,
        params: params
      })
          .success(function (result) {
            // promise resolve
            deferred.resolve(result);
          })
          .error(function (result) {
            // called asynchronously if an error occurs
            // or server returns response with an error status.
            deferred.reject('Erreur request : ' + result);
          });
      return deferred.promise;
    };
    

    test spec:

    it('should call getFilterData() in bindFilters()', function () {
        spyOn(scope, 'getFilterData');
        scope.bindFilters();
        expect(scope.getFilterData).toHaveBeenCalled();
      });
    

    I'm getting an error called "TypeError: Cannot read property 'then' of undefined".

    How can I write an unit test for those two methods using karma.

    Update:

    1.how do we can test the success and error of scope.getFilterData()

    2 .then function in scope.bindFilters() function.

    Please help..