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)
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!