我正在尝试编写业力/茉莉花测试,我想对模拟如何在正在返回诺言的服务上工作进行一些解释。我解释一下我的情况:
我有一个控制器,在其中执行以下调用:
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参数。我不了解如何模拟所有服务内容(服务,承诺,然后)
因此,如果您的服务是否按预期进行响应,那么您想测试一下吗?然后,您宁愿在服务上对此进行测试。基于单元测试承诺的方法可能如下所示:
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为每个it()规格设置了模拟程序。并且我们进行设置$q并$rootScope进行后续处理。
$injector
inject()
$httpBackend
it()
$q
$rootScope
这是测试服务方法是否返回承诺的方法:
it('should return a promise', function () { expect(mapService.getMapUuid('uuid', true).then).toBeDefined(); });
由于promise始终具有.then()方法,因此我们可以检查此属性以查看它是否为promise(当然,其他对象也可以使用此方法)。
.then()
接下来,您可以测试您获得的具有适当价值的承诺。您可以进行设置以deferred明确解决。
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]); });
希望这可以帮助!