我试图写一个业务/茉莉花测试,我想要一些关于mocks如何在一个正在退回承诺的服务上的解释。我解释我的情况:
我有一个控制器,我在其中进行以下调用:
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,$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,3] } }); }));
您可以看到,您不需要使用$ inject,因为您可以直接注入所需的服务。如果您想在整个测试中使用正确的服务名称,您可以使用前缀和后缀“_”注入它们,注入()足够聪明地识别出您的意思。我们还为每个it()规范设置$ httpBackend mock。并且我们设置$ q和$ rootScope进行后续处理。
以下是您如何测试您的服务方法返回承诺:
it('should return a promise',function () { expect(mapService.getMapUuid('uuid',true).then).toBeDefined(); });
由于承诺总是有一个.then()方法,我们可以检查这个属性,看看它是否是一个承诺(当然,其他对象也可以使用这个方法)。
接下来,您可以用适当的价值测试您得到的解决方案的承诺。您可以设置您明确解析的延迟。
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]); });
希望这可以帮助!