karma-jasmine - TypeError:创建单元测试时无法读取 null 的属性“addEventListener” - Jasmine(Angular)
问题描述
我对 Jasmine 进行了单元测试,我得到的是这个
TypeError: Cannot read property 'addEventListener' of null
实际代码是这样的...
ngAfterViewInit() {
this.autoCompleteInput = <HTMLInputElement>document.querySelector('.search-input');
this.autoCompleteInput.addEventListener('blur', this.onBlur.bind(this));
this.autoCompleteInput.addEventListener('input', this.onInput.bind(this));
this.autoCompleteInput.addEventListener('focus', this.onFocus.bind(this));
this.renderer.setAttribute(this.inputRef.nativeElement, 'aria-autocomplete', 'both');
if (this.filter !== undefined && this.filter !== null && this.filter !== '') {
this.filter = '';
}
}
addEventListener 的第一行有效
this.autoCompleteInput.addEventListener('blur', this.onBlur.bind(this));
但其余的因ng test --code-coverage --watch=false而失败
当我检查报告时,我看到:
我不明白为什么 onBlur 测试很好,而其他的却不行?
这是我的茉莉花代码:
import { TestBed, async, ComponentFixture, fakeAsync, tick } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '@angular/core';
import { AutocompleteComponent } from './autocomplete.component';
import { filter } from 'lodash';
describe('Auto Complete Component', () => {
let autoCompleteComponent: AutocompleteComponent;
let fixture: ComponentFixture<AutocompleteComponent>;
let autoCompleteInput: HTMLInputElement;
let filteredItems: string[] = [];
let $window, $provide, listeners;
// let rendered: DebugElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule.withRoutes([])
],
declarations: [
AutocompleteComponent
],
providers: [AutocompleteComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents().then(() => {
fixture = TestBed.createComponent(AutocompleteComponent);
autoCompleteComponent = fixture.componentInstance;
fixture.detectChanges();
});
}));
it('should create call ngOnChanges ', () => {
jasmine.createSpy('ngOnChanges').and.callThrough();
autoCompleteComponent.ngOnChanges();
expect(autoCompleteComponent.ngOnChanges()).toHaveBeenCalled();
});
it('should create filterItems() Function ', () => {
jasmine.createSpy('filterItems').and.callThrough();
expect(autoCompleteComponent.filterItems).toBeUndefined();
});
it('should create call clearFocus ', () => {
jasmine.createSpy('clearFocus').and.callThrough();
autoCompleteComponent.clearFocus();
expect(autoCompleteComponent.clearFocus()).toHaveBeenCalled();
});
it('should call onBlur Event ', () => {
jasmine.createSpy('onBlur').and.callThrough();
autoCompleteComponent.onBlur(event);
expect(autoCompleteComponent.onBlur(event)).toHaveBeenCalled();
});
it('should call onItemSelect Event ', () => {
let item = '';
jasmine.createSpy('onItemSelect').and.callThrough();
jasmine.createSpy('clearFocus').and.callThrough();
expect(autoCompleteComponent.onItemSelect(event, item)).toHaveBeenCalled();
expect(autoCompleteComponent.itemSelect.emit(item)).toHaveBeenCalled();
expect(autoCompleteComponent.clearFocus()).toHaveBeenCalled();
});
it('should call onFocus Event ', () => {
jasmine.createSpy('onFocus').and.callThrough();
autoCompleteComponent.onFocus(event);
expect(autoCompleteComponent.autoCompleteInput.focus()).toHaveBeenCalled;
// expect(autoCompleteComponent.onFocus(event)).toHaveBeenCalled();
});
it('should call onInput Event ', () => {
jasmine.createSpy('onInput').and.callThrough();
autoCompleteComponent.onInput(event);
expect(autoCompleteComponent.onInput(event)).toHaveBeenCalled();
});
});
解决方案
经过大量实验,我找到了答案,我希望这对其他人有所帮助。
这是解决方案:
ngAfterViewInit() {
this.autoCompleteInput = <HTMLInputElement>document.querySelector('.search-input');
console.log('Add Event Listener: ', this.autoCompleteInput);
this.bindOnBlurStateEventCallback();
this.bindOnInputStateEventCallback();
this.bindOnFocusStateEventCallback();
this.renderer.setAttribute(this.autoCompleteInput, 'aria-autocomplete', 'both');
if (this.filter !== undefined && this.filter !== null && this.filter !== '') {
this.filter = '';
}
}
public bindOnBlurStateEventCallback(): void {
this.autoCompleteInput.addEventListener('blur', this.onBlur.bind(this));
document.querySelector('.search-input').addEventListener('blur', () => {
console.log('You selected: ', this.autoCompleteInput.value);
});
}
public bindOnInputStateEventCallback(): void {
this.autoCompleteInput.addEventListener('input', this.onInput.bind(this));
}
public bindOnFocusStateEventCallback(): void {
this.autoCompleteInput.addEventListener('focus', this.onFocus.bind(this));
}
在 spec.ts 文件中:
it('adds listener events', function () {
spyOn(document, 'addEventListener').and.callThrough();
spyOn(window, 'addEventListener').and.callThrough();
expect(document.addEventListener.prototype).not.toBeTruthy;
expect(window.addEventListener.prototype).not.toBeTruthy;
expect(document.addEventListener.prototype).toBeTruthy;
expect(window.addEventListener.prototype).toBeTruthy;
});
你有它!
推荐阅读
- c# - 每个案例 NUnit 的参数化测试与测试方法
- nestjs - NestJS enableVersioning 未定义?
- python - 使用 numpy 数组打印格式
- c# - 使用代码优先的 Entiy 框架在模型类中建立关系
- r - ggplot2:在堆积条形图中显示值(值隐藏在条形图后面)
- typescript - Typescript 中的条件守卫
- julia - 如何访问 Julia 中的扩展帮助模式?
- python - 根据列表中的字符串拆分字符串列表
- vue.js - 使用 vue 项目构建期间出现 Tailwind 错误
- java - 为什么我在测试时出现 NullPointerException?