Mock angular обслуживание/обещание в карма/жасмине

Я пытаюсь написать тест на карма/жасмин, и мне бы хотелось, чтобы некоторые объяснения о том, как макеты работают над сервисом, который возвращает обещание. Я объясняю свою ситуацию:

У меня есть контроллер, в котором я вызываю следующий вызов:

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

    ...

Вот как мой сервис:

(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;
        }
    };
}

})();

И наконец, вот мой unit test:

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();
});
});

То, что я действительно хочу сделать, - это иметь объект ответа ({"elements:...}) как параметр данных функции fillMapDatas. Я не понимаю, как издеваться над всеми сервисами (услуга, обещание, то)

Ответы

Ответ 1

Итак, вы хотите протестировать, если ваши ответы службы ожидаются? Тогда это то, что вы бы предпочли проверить на службе. Unit test методы, основанные на обещаниях, могут выглядеть следующим образом:

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]
    }
  });
}));

Как вы можете видеть, вам не нужно использовать $injector, так как вы можете напрямую вставлять нужные вам службы. Если вы хотите использовать правильные имена служб во время своих тестов, вы можете вводить их с префиксами и суффиксами "_", inject() достаточно умен, чтобы распознать, какую услугу вы имеете в виду. Мы также настраиваем $httpBackend mock для каждой спецификации it(). И мы установили $q и $rootScope для последующей обработки.

Здесь вы можете проверить, что ваш метод обслуживания возвращает обещание:

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

Поскольку у обещания всегда есть метод .then(), мы можем проверить это свойство, чтобы убедиться, что это обещание или нет (конечно, другие объекты тоже могут иметь этот метод).

Затем вы можете проверить свое обещание, которое вы получите, с правильной стоимостью. Вы можете сделать это, настроив deferred, который вы явно разрешите.

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]);
});

Надеюсь, это поможет!