我一直试图找出一种方法来测试我的指令的focusElement
函数。但不知何故,每当我在测试中调用该函数时,classElements
变量都是未定义的。有人有线索吗?
这是指令功能
$scope.focusElement = function() {
if (attrs.focusToClass) {
$scope.classElements = angular.element(document.querySelectorAll('.' + attrs.focusToClass));
if (attrs.focusToClassIndex) {
// Focus to the class with the specified index.
// Index should be within the length of elements and must not be a negative number.
if (attrs.focusToClassIndex < $scope.classElements.length && attrs.focusToClassIndex >= 0) {
$scope.elementToFocus = $scope.classElements[attrs.focusToClassIndex];
}
} else {
// Goes to the first index if the index is not specified.
$scope.elementToFocus = $scope.classElements[0];
}
} else if (attrs.focusToId) {
// Focus to the given ID
$scope.elementToFocus = angular.element(document.querySelector('#' + attrs.focusToId))[0];
}
if ($scope.elementToFocus) {
$scope.elementToFocus.focus();
}
}
这是单元测试代码。
describe('focusElement function', function () {
var targetElement;
var element;
var elementScope;
var elementToFocus;
beforeEach(function() {
targetElement = $compile('<div id="targetDiv" class="targetClass"><span id="targetSpan" class="targetClass"></span></div>')($rootScope);
$rootScope.$apply();
});
it('should return the class element with index 0', function() {
element = $compile('<div next-focus focus-to-class="targetClass"></div>')($rootScope);
});
it('should return the class element with the specific index within the range', function() {
element = $compile('<div next-focus focus-to-class="targetClass" focus-to-class-index="1"></div>')($rootScope);
});
it('should return the class element with the specific index outside the range', function() {
element = $compile('<div next-focus focus-to-class="targetClass" focus-to-class-index="-1"></div>')($rootScope);
});
it('should return the id element', function() {
element = $compile('<div next-focus focus-to-id="targetDiv"></div>')($rootScope);
});
afterEach(function() {
elementScope = element.scope();
spyOn(elementScope, 'focusElement').and.callThrough();
elementScope.focusElement();
console.log(elementScope.classElements);
expect(elementScope.focusElement).toHaveBeenCalled();
expect(elementScope.elementToFocus).toBeDefined();
expect(elementScope.elementToFocus.focus).toHaveBeenCalled();
});
});
答案 0 :(得分:0)
错误是您在包含被测单元的代码中直接使用document
的结果。解决方案是重构代码以不直接使用document
,而是使用jQuery
样式$()
语法来获得相同的行为,使$()
操作的上下文成为可注入的依赖,然后在你的单元测试中使用诸如fixtures
之类的东西来在测试期间注入一个众所周知的上下文。由于您已经使用了Jasmine,因此您可能希望查看jasmine-jquery
以获得方便的API以便轻松完成此操作。
(或者,在此特定情况下,您还可以在document.querySelectorAll
回调中设置存根/模拟beforeEach()
。)
这就是问题所在的问题,以及如何解决问题(高级别),但在继续之前了解Karma会有所帮助。
跳过许多更精细的点,基本上业力包括三个组合成一个单独的应用程序:
files
中配置)。此服务器的结构为Express JS应用程序,如果您想要集成自定义中间件,这将非常有用。例如。在服务器上公开其他路径,以便为您的Angular应用程序代码提供虚拟API服务器以进行交互。要记住的特定路径是'/ base',它对应于您的Karma配置(工作目录)中定义的项目目录。files
中加载included: true
的所有条目的方式,基本上为{ {1}}标签)。<script>
类型插件交互的地方,也是Karma如何能够恢复输出并确定测试是否成功的地方。 第2点和第3点有影响,特别是环境(karma-jasmine
)和HTML(window
)应该基本上被视为Karma的内部实现细节,而不是在测试期间依赖。这意味着您的测试代码也不应该依赖于这些细节。这就是为什么你应该重构你的代码以传递document
作为依赖项的上下文,然后你可以在测试中传递一个众所周知的fixture,并在你的实际应用程序中传递正常的上下文。