我试图写一个业务/茉莉花测试,我想要一些关于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]);
});
希望这可以帮助!