web-dev-qa-db-fra.com

maquette angular service / promesse dans un test de karma / jasmin

J'essaie d'écrire un test de karma/jasmin et j'aimerais avoir des explications sur la façon dont les simulations fonctionnent sur un service qui renvoie une promesse. J'explique ma situation:

J'ai un contrôleur dans lequel je fais l'appel suivant:

mapService.getMapByUuid(mapUUID, isEditor).then(function(datas){
    fillMapDatas(datas);
});

function fillMapDatas(datas){
    if($scope.elements === undefined){
        $scope.elements = [];
    }
 //Here while debugging my unit test, 'datas' contain the promise javascript object instead //of my real reponse.
   debugger;
    var allOfThem = _.union($scope.elements, datas.elements);

    ...

Voici comment est mon service:

(function () {
'use strict';

var serviceId = 'mapService';

angular.module('onmap.map-module.services').factory(serviceId, [
    '$resource',
    'appContext',
    'restHello',
    'restMap',
    serviceFunc]);

function serviceFunc($resource, appContext, restHello, restMap) {

    var Maps = $resource(appContext+restMap, {uuid: '@uuid', editor: '@editor'});

    return{          
        getMapByUuid: function (uuid, modeEditor) {
            var maps = Maps.get({'uuid' : uuid, 'editor': modeEditor});
            return maps.$promise;
        }
    };
}

})();

Et enfin, voici mon test unitaire:

describe('Map controller', function() {
var $scope, $rootScope, $httpBackend, $timeout, createController, MapService, $resource;

beforeEach(module('onmapApp'));

beforeEach(inject(function($injector) {
    $httpBackend = $injector.get('$httpBackend');
    $rootScope = $injector.get('$rootScope');
    $scope = $rootScope.$new();

    var $controller = $injector.get('$controller');

    createController = function() {
        return $controller('maps.ctrl', {
            '$scope': $scope
        });
    };
}));

afterEach(function() {
    $httpBackend.verifyNoOutstandingExpectation();
    $httpBackend.verifyNoOutstandingRequest();
});

var response = {"elements":[1,2,3]};

it('should allow user to get a map', function() {

    var controller = createController();
    $httpBackend.expect('GET', '/onmap/rest/map/MY-UUID?editor=true')
        .respond({
            "success": response
        });


// hope to call /onmap/rest/map/MY-UUID?editor=true url and hope to have response as the fillMapDatas parameter
    $scope.getMapByUUID('MY-UUID', true); 

    $httpBackend.flush();
});
});

Ce que je veux vraiment faire, c'est avoir mon objet de réponse ({"elements: ...}) comme paramètre de données de la fonction fillMapDatas. Je ne comprends pas comment se moquer de toutes les choses de service (service, promesse, puis)

17
clement

Vous souhaitez donc tester, si votre service répond comme prévu? Ensuite, c'est quelque chose que vous préférez tester sur le service. Les méthodes basées sur les promesses de test unitaire pourraient ressembler à ceci:

var mapService, $httpBackend, $q, $rootScope;

beforeEach(inject(function (_mapService_, _$httpBackend_, _$q_, _$rootScope_) {
  mapService = mapService;
  $httpBackend = _$httpBackend_;
  $q = _$q_;
  $rootScope = _$rootScope_;

  // expect the actual request
  $httpBackend.expect('GET', '/onmap/rest/map/uuid?editor=true');

  // react on that request
  $httpBackend.whenGET('/onmap/rest/map/uuid?editor=true').respond({
    success: {
      elements: [1, 2, 3]
    }
  });
}));

Comme vous pouvez le voir, vous n'avez pas besoin d'utiliser $injector, Car vous pouvez injecter directement les services dont vous avez besoin. Si vous souhaitez utiliser les noms de service corrects tout au long de vos tests, vous pouvez leur injecter des préfixes et des suffixes "_", inject() est suffisamment intelligent pour reconnaître de quel service vous parlez. Nous configurons également la maquette $httpBackend Pour chaque spécification it(). Et nous avons configuré $q Et $rootScope Pour un traitement ultérieur.

Voici comment tester que votre méthode de service renvoie une promesse:

it('should return a promise', function () {
  expect(mapService.getMapUuid('uuid', true).then).toBeDefined();
});

Puisqu'une promesse a toujours une méthode .then(), nous pouvons vérifier cette propriété pour voir si c'est une promesse ou non (bien sûr, d'autres objets pourraient aussi avoir cette méthode).

Ensuite, vous pouvez tester la promesse que vous obtenez résout avec la valeur appropriée. Vous pouvez faire cela en configurant un deferred que vous résolvez explicitement.

it('should resolve with [something]', function () {
  var data;

  // set up a deferred
  var deferred = $q.defer();
  // get promise reference
  var promise = deferred.promise;

  // set up promise resolve callback
  promise.then(function (response) {
    data = response.success;
  });

  mapService.getMapUuid('uuid', true).then(function(response) {
    // resolve our deferred with the response when it returns
    deferred.resolve(response);
  });

  // force `$digest` to resolve/reject deferreds
  $rootScope.$digest();

  // make your actual test
  expect(data).toEqual([something]);
});

J'espère que cela t'aides!

25
Pascal Precht