对指令进行单元测试 - 无法强制使用虚假数据
Posted
技术标签:
【中文标题】对指令进行单元测试 - 无法强制使用虚假数据【英文标题】:Unit testing a directive - Unable to force a fake data 【发布时间】:2015-02-25 10:46:56 【问题描述】:我正在尝试了解如何在以下情况下对我的指令进行单元测试。
基本上,我正在尝试对具有控制器的指令进行单元测试。在加载此指令时,控制器通过服务发出 http 请求,该服务再次将一些数据带到控制器,然后将这些数据提供给指令视图。
在我的理解中,我应该这样做:
$httpBackend 用于在 http 请求完成时避免异常; 填充虚假数据,以便能够对具有差异行为的指令进行单元测试 编译指令如您所见,到目前为止,我一直在尝试用虚假数据覆盖服务。到目前为止我无法完成的工作。
现在出现了一些疑问。
正如您在我的控制器中看到的那样。我正在为视图提供整个服务:
$scope.ItemsDataservice = ItemsDataservice;
是什么让我相信我的覆盖服务的方法应该有效。
我的问题:
在下面的场景中,我知道我可以覆盖服务来操作数据,甚至可以覆盖控制器来按范围操作数据。
在这里做什么是正确的? 我理解错了吗? 我在混合单元测试吗?
在我当前的单元测试代码中,当我应用假数据(或不应用)时,没有任何区别:
ItemsDataservice.items = DATARESULT;
ItemsDataservice.items = null;
控制器:
angular.module('app')
.controller('ItemsCtrl', function ($scope, $log, ItemsDataservice)
$scope.ItemsDataservice = ItemsDataservice;
$scope.ItemsDataservice.items = null;
$scope.loadItems = function()
var items = [];
ItemsDataservice.getItems().then(function(resp)
if (resp.success != 'false')
for (resp.something ... )
items.push( ... );
;
ItemsDataservice.items = items;
;
, function(e)
$log.error('Error', e);
);
;
$scope.loadItems();
);
服务:
angular.module('app')
.service('ItemsDataservice', function ItemsDataservice($q, $http)
ItemsDataservice.getItems = function()
var d = $q.defer();
var deffered = $q.defer();
var url = 'http://some-url?someparameters=xxx'
$http.get(url)
.success(function (d)
deffered.resolve(d);
);
return deffered.promise;
;
return ItemsDataservice;
);
指令:
angular.module('app')
.directive('items', function ()
return
templateUrl: '/items.html',
restrict: 'A',
replace: true,
controller: 'ItemsCtrl'
;
);
单元测试指令:
ddescribe('Directive: Items', function ()
var element, scope, _ItemsDataservice_, requestHandler, httpBackend;
var URL = 'http://some-url?someparameters=xxx';
var DATARESULT = [ ... ];
// load the directive's module
beforeEach(module('app'));
beforeEach(module('Templates')); // setup in karma to get template from .html
beforeEach(inject(function ($rootScope, ItemsDataservice)
httpBackend = $httpBackend;
scope = $rootScope.$new();
_ItemsDataservice_ = ItemsDataservice;
requestHandler = httpBackend.when('GET', URL).respond(200, 'ok');
));
afterEach(function()
//httpBackend.verifyNoOutstandingExpectation();
//httpBackend.verifyNoOutstandingRequest();
);
it('Show "No Items available" when empty result', inject(function ($compile)
_ItemsDataservice_.items = null;
element = angular.element('<div data-items></div>');
element = $compile(element)(scope);
scope.$digest();
element = $(element);
expect(element.find('.msg_noresult').length).toBe(1);
));
it('Should not show "No Items available" when data available ', inject(function ($compile)
_ItemsDataservice_.items = DATARESULT;
element = angular.element('<div data-items></div>');
element = $compile(element)(scope);
scope.$digest();
element = $(element);
expect(element.find('.msg_noresult').length).toBe(0);
));
);
【问题讨论】:
【参考方案1】:我解决了这个问题。
更改了这一行:
element = $compile(element)(scope);
到这一行:
element = $compile(element.contents())(scope);
唯一的区别是 jquery 方法 .contents()
我还不明白为什么。但它解决了。
更新:
我刚刚发现的另一件事对我非常有用。 您可以在 httpBackend 上使用正则表达式:
httpBackend.whenGET(/.*NameOfThePageXXX\.aspx.*/).respond(200, 'ok');
因此,如果您只想避免异常,则无需担心使用完全相同的参数等。
【讨论】:
以上是关于对指令进行单元测试 - 无法强制使用虚假数据的主要内容,如果未能解决你的问题,请参考以下文章
在 Angular 中使用 Jasmine 使用 *ngIf 指令时,如何对元素是不是可见进行单元测试