web-dev-qa-db-ja.com

mock angular service / promise in karma / jasmine test

私はカルマ/ジャスミンテストを作成しようとしています。モックがプロミスを返すサービスにどのように取り組んでいるかについて、いくつかの説明をお願いします。私は私の状況を説明します:

次の呼び出しを行うコントローラーがあります。

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

})();

そして最後に、これが私の単体テストです:

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関数のdatasパラメータとして持つことです。

17
clement

サービスが期待どおりに応答するかどうかをテストしますか?次に、これはサービスでテストしたいものです。単体テストのpromiseベースのメソッドは次のようになります。

_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()は、どのサービスを意味するかを認識するのに十分なほどスマートです。また、it()仕様ごとに_$httpBackend_モックを設定します。そして、後で処理するために_$q_と_$rootScope_を設定します。

サービスメソッドがpromiseを返すことをテストする方法は次のとおりです。

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

Promiseには常に.then()メソッドがあるため、このプロパティをチェックして、promiseかどうかを確認できます(もちろん、他のオブジェクトもこのメソッドを持つことができます)。

次に、適切な値で解決する約束をテストできます。明示的に解決する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]);
});
_

お役に立てれば!

25
Pascal Precht