Angular 7 testing - 模拟带去抖时间的输入事件
Angular 7 testing - simulate input event with debounce time
在开始这个问题之前。我知道,有很多像我这样的类似问题。但是没有任何解决方案能够帮助我。
我用 rxjs 创建了一个自定义自动完成功能,想测试是否在输入事件上调用了一个方法。但是错误说该方法从未被调用过,例如:
Expected spy CityService.getLocation to have been called with [ 'mun' ] but it was never called.
html
我通过 async
管道在 HTML 中订阅了我的可观察对象。
<input type="text" [(ngModel)]="location" class="form-control" id="locationSearchInput"/>
<div class="spacer">
<p class="invalid-feedBack" *ngIf="searchFailed && location.length > 0">Nothing found.</p>
<ul id="search" *ngFor="let item of (search | async)">
<li class="resultItem" type="radio" (click)="location = item">{{item}}</li>
</ul>
</div>
组件
ngOnInit(): void {
this.search = fromEvent(document.getElementById('locationSearchInput'), 'input').pipe(
debounceTime(750),
distinctUntilChanged(),
map((eventObj: Event) => (<HTMLInputElement>eventObj.target).value),
switchMap((term: string) => this.cityService.getLocation(term)) <== should get called
);
}
测试
const cityServiceStub: CityService = jasmine.createSpyObj('CityService', ['getLocation']);
...
it('should search for location on init', async(() => {
const spy = (<jasmine.Spy>cityServiceStub.getLocation).and.returnValue(['Munich', 'Münster']);
fixture.detectChanges();
const rendered: DebugElement = fixture.debugElement.query(By.css('#locationSearchInput'));
rendered.nativeElement.value = 'mun';
rendered.nativeElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
fixture.whenStable().then(() => {
console.log(rendered.nativeElement.value);
expect(spy).toHaveBeenCalledWith('mun');
});
}));
我也尝试过将 fakeAsync
与 tick(750)
一起使用。但没有任何帮助。测试中的 console.log
还显示一个空字符串作为输入值。所以也许我模拟了一个错误的事件。
此代码在测试之外是否有效?您没有 post 编辑整个组件,但在您编辑的片段中 post 我看不到任何地方都在进行订阅。 Observable 在至少有一个订阅之前不会开始发射(参见 here)。
我在我的副项目中实施了您的测试,它仅在订阅 Observable 后才开始工作,如下所示:
fromEvent(document.getElementById('locationSearchInput'), 'input').pipe(
debounceTime(750),
distinctUntilChanged(),
map((eventObj: Event) => (<HTMLInputElement>eventObj.target).value),
switchMap((term: string) => this.cityService.getLocation(term))
).subscribe()
您应该为 Observable
打电话给 .subscribe()
。你应该 return 一个 Observable
在 switchMap
里面,所以,你不能 return 一个带有间谍的数组,但是 Observable: const spy = (cityServiceStub.getLocation as jasmine.Spy).and.returnValue(of(['Munich', 'Münster']));
我的测试使用了以下配置:
it('should search for location on init', fakeAsync(() => {
const spy = (<jasmine.Spy>cityServiceStub.getLocation).and.returnValue(of(['Munich', 'Münster']));
fixture.detectChanges();
const rendered: DebugElement = fixture.debugElement.query(By.css('#locationSearchInput'));
rendered.nativeElement.value = 'mun';
rendered.nativeElement.dispatchEvent(new Event('input'));
tick(750);
fixture.detectChanges();
expect(spy).toHaveBeenCalledWith('mun');
}));
我错过了 return ['Munich', 'Münster']
作为 Observable 与 of()
运算符。我应该使用 tick(750)
来等待事件变化的特定去抖时间。
在开始这个问题之前。我知道,有很多像我这样的类似问题。但是没有任何解决方案能够帮助我。
我用 rxjs 创建了一个自定义自动完成功能,想测试是否在输入事件上调用了一个方法。但是错误说该方法从未被调用过,例如:
Expected spy CityService.getLocation to have been called with [ 'mun' ] but it was never called.
html
我通过 async
管道在 HTML 中订阅了我的可观察对象。
<input type="text" [(ngModel)]="location" class="form-control" id="locationSearchInput"/>
<div class="spacer">
<p class="invalid-feedBack" *ngIf="searchFailed && location.length > 0">Nothing found.</p>
<ul id="search" *ngFor="let item of (search | async)">
<li class="resultItem" type="radio" (click)="location = item">{{item}}</li>
</ul>
</div>
组件
ngOnInit(): void {
this.search = fromEvent(document.getElementById('locationSearchInput'), 'input').pipe(
debounceTime(750),
distinctUntilChanged(),
map((eventObj: Event) => (<HTMLInputElement>eventObj.target).value),
switchMap((term: string) => this.cityService.getLocation(term)) <== should get called
);
}
测试
const cityServiceStub: CityService = jasmine.createSpyObj('CityService', ['getLocation']);
...
it('should search for location on init', async(() => {
const spy = (<jasmine.Spy>cityServiceStub.getLocation).and.returnValue(['Munich', 'Münster']);
fixture.detectChanges();
const rendered: DebugElement = fixture.debugElement.query(By.css('#locationSearchInput'));
rendered.nativeElement.value = 'mun';
rendered.nativeElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
fixture.whenStable().then(() => {
console.log(rendered.nativeElement.value);
expect(spy).toHaveBeenCalledWith('mun');
});
}));
我也尝试过将 fakeAsync
与 tick(750)
一起使用。但没有任何帮助。测试中的 console.log
还显示一个空字符串作为输入值。所以也许我模拟了一个错误的事件。
此代码在测试之外是否有效?您没有 post 编辑整个组件,但在您编辑的片段中 post 我看不到任何地方都在进行订阅。 Observable 在至少有一个订阅之前不会开始发射(参见 here)。
我在我的副项目中实施了您的测试,它仅在订阅 Observable 后才开始工作,如下所示:
fromEvent(document.getElementById('locationSearchInput'), 'input').pipe(
debounceTime(750),
distinctUntilChanged(),
map((eventObj: Event) => (<HTMLInputElement>eventObj.target).value),
switchMap((term: string) => this.cityService.getLocation(term))
).subscribe()
您应该为 Observable
打电话给 .subscribe()
。你应该 return 一个 Observable
在 switchMap
里面,所以,你不能 return 一个带有间谍的数组,但是 Observable: const spy = (cityServiceStub.getLocation as jasmine.Spy).and.returnValue(of(['Munich', 'Münster']));
我的测试使用了以下配置:
it('should search for location on init', fakeAsync(() => {
const spy = (<jasmine.Spy>cityServiceStub.getLocation).and.returnValue(of(['Munich', 'Münster']));
fixture.detectChanges();
const rendered: DebugElement = fixture.debugElement.query(By.css('#locationSearchInput'));
rendered.nativeElement.value = 'mun';
rendered.nativeElement.dispatchEvent(new Event('input'));
tick(750);
fixture.detectChanges();
expect(spy).toHaveBeenCalledWith('mun');
}));
我错过了 return ['Munich', 'Münster']
作为 Observable 与 of()
运算符。我应该使用 tick(750)
来等待事件变化的特定去抖时间。