0
votes

I'm still new to unit testing, and i was trying to test a function on my component controller, which use a service for an api call but i notice that when i run the test its not going inside .then of the request return .

here is my component 'arSchoolComponent':

var arSchoolComponent = {
templateUrl: "ar-school.component.html",
controller: arSchoolComponentCtrl,
controllerAs: 'schoolCtrl'
};

arSchoolComponentCtrl.$inject = [
    "$schoolsService",
    "$permissionService",
    "$stateParams",
    "$state",
    "$scope",
    "arAuthenticationService",
    "$mdDialog",
    "$notificationService",
    "$translate"
];

function arSchoolComponentCtrl($schoolsService,
                               $permissionService,
                               $stateParams,
                               $state,
                               $scope,
                               arAuthenticationService,
                               $mdDialog,
                               $notificationService,
                               $translate) {


// @variables
var vm = this;
vm.loading = false;
vm.selectedSchool = null;

// @methods
vm.getSchool = getSchool;

vm.$onInit = function () {
  //this is equal to getSchool(1)
  getSchool(vm.currentUser.information.staff.schools[0].schoolId);
};

/**
 * Load school data from server
 *
 * @param id
 */
function getSchool(id) {
    preloader.on();

    if (!vm.loading) {
        vm.loading = true;

        var request = $schoolsService.getSchool(id);

        request.then(function (response) {
            vm.selectedSchool = response.data;
            vm.loadCompleted = true;
        }).then(function () {
            vm.loading = false;
            preloader.off();
        });
    }
}


}

here is my service '$schoolsService' :

var arSchoolsService = [
'UtilityService',
'$q',
function($utility, $q) {

    var _this = this;

    //@variables
    _this.user = null;
    _this.baseUrl = 'api/school'; // Server base url for request
    _this.selectedSchool = null; // Selected School
    _this.schools = []; // Array of schools
    _this.validationError = false;

    var service = {
        getSchool: getSchool

    };

    return service;

    //@methods

    /**
     * Return one school
     *
     * @param schoolId
     */
    function getSchool(schoolId) {
        return $utility.sendRequest('GET', _this.baseUrl + '/' + schoolId);
    }
}

here is my unit test :

describe('Unit - Component: school', function () {

beforeEach(module('activityRight.module', 'mockedSchoolJSON'));

var ctrl;
var SignInCtrl;

var $componenetController;
var $schoolsService;
var $permissionService;
var $state;
var arAuthenticationService;
var $translate, $scope, $notificationService, $auth;
var deferred;
var CONFIG;
var $httpBackend;
var $defaultJSON;

beforeEach(inject(
    function (_$componentController_, _$schoolsService_, _$permissionService_, _$stateParams_, _$state_, $rootScope, _arAuthenticationService_,
        _$notificationService_, _$translate_, _$auth_, $q, _$httpBackend_, defaultJSON, $injector) {
        $componenetController = _$componentController_;
        $schoolsService = _$schoolsService_;
        $permissionService = _$permissionService_;
        $stateParams = _$stateParams_;
        $state = _$state_;
        $scope = $rootScope.$new();
        arAuthenticationService = _arAuthenticationService_;
        $notificationService = _$notificationService_;
        $translate = _$translate_;
        $auth = _$auth_;
        deferred = $q.defer();
        $httpBackend = _$httpBackend_;
        CONFIG = $injector.get('CONFIG');
        $defaultJSON = defaultJSON

        ctrl = $componenetController('arSchoolComponent', {
            "$schoolsService": $schoolsService,
            "$permissionService": $permissionService,
            "$stateParams": $stateParams,
            "$state": $state,
            "$scope": $scope,
            "arAuthenticationService": arAuthenticationService,
            "$notificationService": $notificationService,
            "$translate": $translate
        });

        SignInCtrl = $componenetController('arSigninComponent', {
            '$auth': $auth,
            'arAuthenticationService': arAuthenticationService,
            '$state': $state,
        });



        SignInCtrl.email = '';
        SignInCtrl.password = '';

        SignInCtrl.authenticate;

        user = arAuthenticationService.sessionUser();

        $permissionService.setUser(user);

        ctrl.$onInit();

        $httpBackend.whenGET('translations/en-ca.json').respond({});
        $httpBackend.whenGET('fb-partials/sign-up.html?ver=1').respond({});
        $httpBackend.whenGET('fb-partials/main.html?ver=1').respond({});
        $httpBackend.when('GET', CONFIG.origin_url + '/api/school/1').respond($defaultJSON.fakeData[0]);
        $httpBackend.flush();
    }
));

// Check for open http requests
afterEach(function () {
    $httpBackend.verifyNoOutstandingExpectation();
    $httpBackend.verifyNoOutstandingRequest();
});

it('`getSchool` should exist and return data depend on id', function () {
    expect(ctrl.getSchool).toBeDefined();
    ctrl.loading = false;
    ctrl.selectedSchool = null;
    spyOn($schoolsService, 'getSchool').and.returnValue(deferred.promise);
    ctrl.getSchool(2);
    expect($schoolsService.getSchool).toHaveBeenCalledTimes(1);
    //will check this error later, need to move one for now
    //expect(ctrl.selectedSchool.schoolId).toBe(2);
});

when i call the function getSchool throught ctrl.getSchool(2) , i spy the service method getSchool spyOn($schoolsService, 'getSchool').and.returnValue(deferred.promise); and the expect($schoolsService.getSchool).toHaveBeenCalledTimes(1); is correct its shows it went through the function and called schoolsService.getSchool but the ctrl.selectedSchool is not updated which mean it didnt go inside .then

I know that im missing something here, could please anyone help regarding this issue.

1

1 Answers

0
votes

You are not resolving the promise, so it will never go to ".then()", you need to resolve it:

spyOn($schoolsService, 'getSchool').and.returnValue(deferred.promise);
ctrl.getSchool(2);
deferred.resolve({school: 'myschooldata'});

also if you want to get the data you set in $httpBackend.when then you shoudn't add the .and.returnValue(...), instead .and.callThrough() and if you do this you probably will need to flush the http request again after calling getSchool() i.e. $httpBackend.flush()