Angular/Jasmine testing with deffered promises

时光总嘲笑我的痴心妄想 提交于 2019-12-22 08:03:53

问题


I am testing a controller using a combination of angular and jasmine, and am not completely sure about using deffered promises.

This is my spec code.

describe('Controller Tests', function(){
    var scope, searchAPI;

    beforeEach(function(){
        var mockSearchAPI = {};
        module('myApp', function($provide){
            $provide.value('searchAPI', mockSearchAPI);
        });
    });

    inject(function($q){
        var testData = {"message":"hi"};
        mockSearchAPI.executeSearch = function(){
            var defer = $q.defer();
            defer.resolve(testData);
            return defer.promise;
        };
    });

    beforeEach('Main Search Controller Tests', function(){

        function($controller, $rootScope, _searchAPI_){
            scope = $rootScope.$new();
            searchAPI = _searchAPI_;
            $controller('MainSearchCtrl', function(){
                $scope: scope,
                searchAPI: searchAPI
            });
            scope.$digest();
        }
    });

    it('should return a promise correctly', function(){
        var field = "testfield";
        var value = "testvalue";
        var pageNumber = 1;
        var promise = scope.processQueryByField(field, value, pageNumber);

        //THIS LINE IS GIVING ME '{}'
        alert(promise); 
    });

});

I am unsure why the line that I am "alerting" is giving me output of '{}'. Shouldn't it be the data struct that I defined as "testData" in the inject function? I am not sure what is going on here. I have tried numerous solutions.

My controller code is basically a wrapper for the service

$scope.processQueryByField = function(field, value, pageNumber){
    return searchAPI.executeSearch(field, value, pageNumber);
}

Shouldn't I just be receiving the value that I defined inside the injector code?


回答1:


I am not exactly sure what expectation you want to set with the promise object, You do not need to test if a promise is resolved, instead you need to test what happens to the data when a promise is resolved.

Example:-

Change your mock to simplify:-

inject(function($q){
    var testData = {"message":"hi"};
    mockSearchAPI.executeSearch = function(){
       return $q.when(testData);
    };
});

Just for a demo i have added one more method in your controller which resolved to a data:-

.controller('MainSearchCtrl', ['$scope','searchAPI', function ($scope, searchAPI) {
        //At this point placing this method on scope is useless
        $scope.processQueryByField = function(field, value, pageNumber){
           return searchAPI.executeSearch(field, value, pageNumber);
        }
        //This when invoked will update the searchResults in the model.
        $scope.populateData = function(){
          $scope.processQueryByField(1,1,1).then(function(data){
            $scope.searchResults = data;
          })
        }
    }]);

Expectation #1:- Test whether when the method is invoked the api method is getting invoked with the expected arguments.

   it('should invoke execute search', function(){
     //Set up a spy on your mock api method
      spyOn(mockSearchAPI,'executeSearch'); 
      var field = "testfield";
      var value = "testvalue";
      var pageNumber = 1;
      scope.processQueryByField(field, value, pageNumber); //invoke scope method with args
      //Test if the mock api method has been called
      expect(mockSearchAPI.executeSearch).toHaveBeenCalled();          
      //test if it has been called with expected arguments.
      expect(mockSearchAPI.executeSearch).toHaveBeenCalledWith(field, value, pageNumber); 
    });

Expectation #2:- Test whether data is populated properly when the promise is resolved.

it('should return a promise correctly', function(){
    var field = "testfield";
    var value = "testvalue";
    var pageNumber = 1;

    var promise = scope.processQueryByField(field, value, pageNumber);
    //This is a useless expectation
    expect(promise).toBeDefined();


    scope.populateData();
    $rootScope.$digest(); //<-- Apply digest cycle, so the promise is resolved
    expect(scope.searchResults).toBeDefined();
    expect(scope.searchResults.message).toEqual("hi");
});

Test Demo



来源:https://stackoverflow.com/questions/25983466/angular-jasmine-testing-with-deffered-promises

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!