私はカルマ/ジャスミンテストを作成しようとしています。モックがプロミスを返すサービスにどのように取り組んでいるかについて、いくつかの説明をお願いします。私は私の状況を説明します:
次の呼び出しを行うコントローラーがあります。
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パラメータとして持つことです。
サービスが期待どおりに応答するかどうかをテストしますか?次に、これはサービスでテストしたいものです。単体テストの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]);
});
_
お役に立てれば!