$timeout
可以被窥探或嘲笑,如此答案所示:
beforeEach(module('app', ($provide) => {
$provide.decorator('$timeout', ($delegate) => {
var timeoutSpy = jasmine.createSpy().and.returnValue($delegate);
// methods aren't copied automatically to spy
return angular.extend(timeoutSpy, $delegate);
});
}));
这里没有太多要测试的东西,因为$timeout
是用匿名函数调用的。出于可测试性的原因,将其公开为范围/控制器方法是有意义的:
$scope.submitFormHandler = function () {
$('#submitForm').click();
};
...
$timeout($scope.submitFormHandler, 2000);
$timeout
然后可以测试间谍:
$timeout.and.stub(); // in case we want to test submitFormHandler separately
scope.submitRequest();
expect($timeout).toHaveBeenCalledWith(scope.submitFormHandler, 2000);
并且内部的逻辑$scope.submitFormHandler
可以在不同的测试中进行测试。
这里的另一个问题是 jQuery 在单元测试中不能很好地工作,并且需要针对真实的 DOM 进行测试(这是在 AngularJS 应用程序中尽可能避免使用 jQuery 的众多原因之一)。可以像这个答案中所示的那样监视/模拟 jQuery API 。
$(...)
可以通过以下方式监视通话:
var init = jQuery.prototype.init.bind(jQuery.prototype);
spyOn(jQuery.prototype, 'init').and.callFake(init);
并且可以模拟:
var clickSpy = jasmine.createSpy('click');
spyOn(jQuery.prototype, 'init').and.returnValue({ click: clickSpy });
请注意,预计模拟函数将返回用于与click
方法链接的 jQuery 对象。
当$(...)
被模拟时,测试不需要#submitForm
在 DOM 中创建夹具,这是隔离单元测试的首选方式。