gpt4 book ai didi

angularjs - 测试需要 Controller 的指令

转载 作者:行者123 更新时间:2023-12-03 06:11:40 25 4
gpt4 key购买 nike

所以我确实看到了另一个问题:How to mock required directive controller in directive UT这基本上是我的问题,但似乎这个帖子的答案是“改变你的设计”。我想确保没有办法做到这一点。我有一个指令声明一个由子指令使用的 Controller 。我现在正在尝试为 Children 指令编写 Jasmine 测试,但我无法让它们在测试中编译,因为它们依赖于 Controller 。它看起来像这样:

addressModule.directive('address', ['$http', function($http){
return {
replace: false,
restrict: 'A',
scope: {
config: '='
},
template: '<div id="addressContainer">' +
'<div ng-if="!showAddressSelectionPage" basic-address config="config"/>' +
'<div ng-if="showAddressSelectionPage" address-selector addresses="standardizedAddresses"/>' +
'</div>',
controller: function($scope)
{
this.showAddressInput = function(){
$scope.showAddressSelectionPage = false;
};

this.showAddressSelection = function(){
$scope.getStandardizedAddresses();
};

this.finish = function(){
$scope.finishAddress();
};
},
link: function(scope, element, attrs) {
...
}
}
}])

子指令:

addressModule.directive('basicAddress360', ['translationService', function(translationService){
return {
replace: true,
restrict: 'A',
scope: {
config: '='
},
template:
'...',
require: "^address360",
link: function(scope, element, attrs, addressController){
...
}
}
}])

Jasmine 测试:

it("should do something", inject(function($compile, $rootScope){
parentHtml = '<div address/>';
subDirectiveHtml = '<div basic-address>';

parentElement = $compile(parentHtml)(rootScope);
parentScope = parentElement.scope();
directiveElement = $compile(subDirectiveHtml)(parentScope);
directiveScope = directiveElement.scope();
$rootScope.$digest();
}));

我没有办法用 Jasmine 测试子指令吗?如果是的话,我错过了什么?即使我可以在没有 Controller 功能的情况下测试指令本身,我也会很高兴。

最佳答案

我可以想到两种方法:

1) 使用两个指令

假设我们有以下指令:

app.directive('foo', function() {
return {
restrict: 'E',
controller: function($scope) {
this.add = function(x, y) {
return x + y;
}
}
};
});

app.directive('bar', function() {
return {
restrict: 'E',
require: '^foo',
link: function(scope, element, attrs, foo) {
scope.callFoo = function(x, y) {
scope.sum = foo.add(x, y);
}
}
};
});

为了测试 callFoo 方法,您可以简单地编译这两个指令并让 bar 使用 foo 的实现:

it('ensures callFoo does whatever it is supposed to', function() {
// Arrange
var element = $compile('<foo><bar></bar></foo>')($scope);
var barScope = element.find('bar').scope();

// Act
barScope.callFoo(1, 2);

// Assert
expect(barScope.sum).toBe(3);
});

Working Plunker .

2) 模拟 foo 的 Controller

这个不太简单,而且有点棘手。您可以使用 element.controller() 获取元素的 Controller ,并使用 Jasmine 模拟它:

it('ensures callFoo does whatever it is supposed to', function() {
// Arrange
var element = $compile('<foo><bar></bar></foo>')($scope);
var fooController = element.controller('foo');
var barScope = element.find('bar').scope();
spyOn(fooController, 'add').andReturn(3);

// Act
barScope.callFoo(1, 2);

// Assert
expect(barScope.sum).toBe(3);
expect(fooController.add).toHaveBeenCalledWith(1, 2);
});

Working Plunker .

当一个指令在其 link 函数中立即使用另一个指令的 Controller 时,就会出现棘手的部分:

app.directive('bar', function() {
return {
restrict: 'E',
require: '^foo',
link: function(scope, element, attrs, foo) {
scope.sum = foo.add(parseInt(attrs.x), parseInt(attrs.y));
}
};
});

在这种情况下,您需要单独编译每个指令,以便您可以在第二个指令使用它之前模拟第一个指令:

it('ensures callFoo does whatever it is supposed to', function() {
// Arrange
var fooElement = $compile('<foo></foo>')($scope);
var fooController = fooElement.controller('foo');
spyOn(fooController, 'add').andReturn(3);

var barElement = angular.element('<bar x="1" y="2"></bar>')
fooElement.append(barElement);

// Act
barElement = $compile(barElement)($scope);
var barScope = barElement.scope();

// Assert
expect(barScope.sum).toBe(3);
expect(fooController.add).toHaveBeenCalledWith(1, 2);
});

Working Plunker .

第一种方法比第二种方法容易得多,但它依赖于第一个指令的实现,即,您不是对事物进行单元测试。另一方面,虽然模拟指令的 Controller 并不那么容易,但它使您可以更好地控制测试并消除对第一个指令的依赖。所以,明智地选择。 :)

最后,我不知道有什么更简单的方法可以完成上述所有操作。如果有人知道更好的方法,请改进我的答案。

关于angularjs - 测试需要 Controller 的指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19227036/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com