使用 jasmine 时,我似乎无法测试其中包含 jquery 选择器或 document.getElementById
的函数。这里有更好的策略吗?我通常不会将选择器放入 Angular 代码中,但这是一种解决方法。
在我正在测试的函数中:
this.scope.login = () => {
($('#login-form')[0] as HTMLFormElement).submit();
// or even
document.getElementById('login-form').submit(); // this is a workaround for browser auto-complete, I normally would not have selectors in angular code.
}
我明白了
TypeError: undefined is not an object (evaluating '$('#login-form')[0].submit')
我尝试过“通过 spy 模拟”,使用spyOn尝试模拟jquery选择器函数并返回一个假元素...但似乎不起作用,或者我做得不对。
我的规范加载了模板(日志正常)。元素也已定义,并且似乎是有效的 Angular 编译元素。
describe('Nav Controller Spec', function() {
beforeEach(function() {
angular.mock.module('App');
inject(function(_$controller_, $rootScope, _userModel_, _$q_, _$httpBackend_, $templateCache, _$compile_) {
scope = $rootScope.$new();
$q = _$q_;
$compile = _$compile_;
$httpBackend = _$httpBackend_;
deferred = _$q_.defer();
html = $templateCache.get('main/components/login/login.tpl.html');
var el = angular.element( html );
element = $compile( el )(scope); //element is valid and works
controller = _$controller_;
userModel = _userModel_;
scope.userModel = userModel;
// tried this... still get error
spyOn($.fn, 'val').and.returnValue('<form></form>');
//if i change to 'init' or 'find', i get 'undefined is not a constructor'
spyOn($.fn, 'init').and.returnValue('<form></form>');
ctrl = controller('loginController', { $scope: scope, $element: element });
$rootScope.$digest();
});
});
it('should login and change the status', function(){
spyOn( ctrl.scope.userModel, 'login' ).and.callThrough();
ctrl.scope.formType = 'login';
ctrl.scope.login(); //fails
expect( ctrl.scope.userModel.login ).toHaveBeenCalled();
});
作为最后的手段,我在 Controller 中使用 document.getElementById('login-form')
尝试了以下操作。但是,我得到 TypeError: undefined is not a constructor (evaluating 'document.getElementById('login-form').submit()')
var mockElement = {
id:"login-form",
parentNode:true
};
var document_getElementById = document.getElementById;
var spy = spyOn(document, "getElementById").and.callFake(function(id){
if(id===mockElement.id){
return mockElement;
}
return document_getElementById(id);
});
最佳答案
事实上,这确实有效。您将需要使用 document.getElementById
进行 stub /监视,因为这就是 jquery 在幕后使用的内容。我只是忘了 stub submit
函数。我没有意识到这一点,因为 jasmine 包装的错误毫无意义。
var mockElement = {
id:"login-form",
parentNode:true,
submit:function(){
return 'cheese';
}
};
var document_getElementById = document.getElementById;
var spy = spyOn(document, "getElementById").and.callFake(function(id){
if(id===mockElement.id){
return mockElement;
}
return document_getElementById(id);
});
关于javascript - 如何对包含 DOM/jquery 选择器的 Angular 1 Controller 进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38381255/