web-dev-qa-db-fra.com

Test de contrôleur Jasmine, espion espéré avoir été appelé

J'ai une méthode définie dans le contrôleur AngularJS qui est appelée à l'initialisation. Je veux le tester avec Jasmine ("jasmine-core": "^2.3.4", "karma": "^0.12.37"). Je suis des tutoriels sur Internet et des questions sur StackOverflow, mais je ne trouve pas la bonne réponse. S'il vous plaît jeter un oeil à ce code:

Contrôleur usersAddUserController:

(function () {
    'use strict';

    angular.module('app.users.addUser')
        .controller('usersAddUserController', ['$scope', 'usersAddUserService', function ($scope, usersAddUserService) {

            usersAddUserService.getCountryPhoneCodes().then(function (phoneCodes) {
                $scope.phoneCodes = phoneCodes;
            });

        }]);
}());

Test au jasmin:

(function () {

    'use strict';

    describe('usersAddUserControllerUnitTest', function () {
        var scope, deferred, objectUnderTest, mockedAddUserService;

        beforeEach(module('app'));

        beforeEach(inject(function ($rootScope, $q, $controller) {
            scope = $rootScope.$new();

            function emptyPromise() {
                deferred = $q.defer();
                return deferred.promise;
            }

            mockedAddUserService = {
                getCountryPhoneCodes: emptyPromise
            };

            objectUnderTest = $controller('usersAddUserController', {
                $scope: scope,
                usersAddUserService: mockedAddUserService
            });
        }));

        it('should call getCountryPhoneCodes method on init', function () {
            //when            
            spyOn(mockedAddUserService, 'getCountryPhoneCodes').and.callThrough();

            deferred.resolve();

            scope.$root.$digest();

            //then
            expect(mockedAddUserService.getCountryPhoneCodes).toHaveBeenCalled();
        });

    });
}());

Après l'exécution des tests, le message d'erreur est le suivant:

PhantomJS 1.9.8 (Windows 7 0.0.0) Les utilisateurs de AddUserControllerUnitTest doivent appeler la méthode getCountryPhoneCodes lors de l'initialisation FAILE

    Expected spy getCountryPhoneCodes to have been called.

Je manque évidemment quelque chose, mais je ne peux pas comprendre ce que c'est. Toute aide serait appréciée.

7
Thomas Weglinski

Vous espionnez la maquette une fois qu'elle a été transmise au contrôleur instancié. 

Essaye ça:

describe('usersAddUserControllerUnitTest', function () {
    var scope, deferred, objectUnderTest, mockedAddUserService, $controller;

    beforeEach(module('app'));

    beforeEach(inject(function ($rootScope, $q, _$controller_) {
        scope = $rootScope.$new();

        function emptyPromise() {
            deferred = $q.defer();
            return deferred.promise;
        }

        mockedAddUserService = {
            getCountryPhoneCodes: emptyPromise
        };

        $controller = _$controller_;
    }));

    function makeController() {    
        objectUnderTest = $controller('usersAddUserController', {
            $scope: scope,
            usersAddUserService: mockedAddUserService
        });
    }

    it('should call getCountryPhoneCodes method on init', function () {
        //when

        spyOn(mockedAddUserService, 'getCountryPhoneCodes').and.callThrough();
        makeController();

        deferred.resolve();

        scope.$root.$digest();

        //then
        expect(mockedAddUserService.getCountryPhoneCodes).toHaveBeenCalled();
    });

});

EDITMerci @juunas d'avoir remarqué le bogue dans ma solution

5
Martin

Vous pouvez fournir la maquette comme ceci:

mockedAddUserService = {
    getCountryPhoneCodes: emptyPromise
};


beforeEach(function () {
    module(function ($provide) {
        $provide.value('usersAddUserService', mockedAddUserService);
    });
});

MODIFIER:

Le code devrait ressembler (comme je ne peux pas le tester) à ceci:

(function () {
    'use strict';

    describe('usersAddUserControllerUnitTest', function () {        
        beforeEach(module('app'));

        var emptyPromise = function() {
            var deferred = $q.defer();
            return deferred.promise;
        }

        var mockedAddUserService = {
            getCountryPhoneCodes: emptyPromise
        };

        beforeEach(function () {
            module(function ($provide) {
                $provide.value('usersAddUserService', mockedAddUserService);
            });
        });

        var scope;
        beforeEach(inject(function ($rootScope, $q, $controller) {
            scope = $rootScope.$new();
            $controller('usersAddUserController', {
                $scope: scope
            });
        }));

        it('should call getCountryPhoneCodes method on init', function () {
            spyOn(mockedAddUserService, 'getCountryPhoneCodes').and.callThrough();

            scope.$root.$digest();

            expect(mockedAddUserService.getCountryPhoneCodes).toHaveBeenCalled();
        });

    });
}());
1
timtos