[英]How to best handle multiple subscriptions to the same observable on the template?
[英]Best testing for observable in template
這是被測試的組件:
@Component({
moduleId: module.id,
selector: 'my-search',
templateUrl: 'search.component.html',
styleUrls: ['search.component.css'],
})
export class SearchComponent implements OnInit {
things: Observable<Thing[]>;
private searchTerms = new Subject<string>();
constructor(private searchService: SearchService) { }
ngOnInit() {
this.things = this.searchTerms
.debounceTime(300)
.distinctUntilChanged()
.switchMap((term: string) => term
? this.searchService.search(term)
: Observable.of<Thing[]>([]));
}
search(term: string) {
this.searchTerms.next(term);
}
}
這是search.component.html:
<form (submit)="search()">
<input #searchBox (keyup)="search(searchBox.value)" />
<button type="submit">Search</button>
</form>
<div *ngIf="(things | async)?.length == 0; else searchResults">No things found.</div>
<ng-template #searchResults>
<div class="search-results">
<div *ngFor="let thing of things | async" class="search-result">
{{thing.id}}
</div>
</div>
</ng-template>
這是失敗的測試:
it('should exhibit issue', fakeAsync(() => {
component.ngOnInit();
fixture.detectChanges();
component.search('123');
tick(300);
fixture.detectChanges();
component.things.subscribe((things) => {
// This fails. (I've tried various things, this is just the latest attempt.)
expect(dom.querySelectorAll('.search-results .search-result').length).toBe(1);
});
}));
無論我做什么,我都看不到DOM的變化。 fixture.detectChanges()
對DOM沒有任何作用。
您如何測試可觀察物?
這對我有用
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
fixture.detectChanges();
app.search('123');
tick(400);
fixture.detectChanges();
const searchNodes = fixture.debugElement.queryAll(By.css('.search-results .search-result')).map((item) => item.nativeElement);
expect(searchNodes.length).toBe(3);
終於讓它工作了。 您可以檢查插件(版本25) ,但這是簡化的解決方案:
it('now works!', async(() => {
// Initialize the component.
component.ngOnInit();
fixture.detectChanges();
// The Observable is now initialized and we can now subscribe.
component.things.subscribe((things) => {
// Now that we've got the data, look for changes.
fixture.detectChanges();
// The DOM/view should now be up to date.
expect(dom.querySelectorAll('.search-results .search-result').length).toBe(1);
});
// Initiate stuff happening.
component.search('123');
}));
強調:
async
而不是fakeAsync
。 detectChanges
,以便更新視圖。 我想說明一件事:在這種情況下, subscribe
是在事件發生之前還是之后(在示例中為search
調用)都無關緊要。 為了預防起見,我將其放置在前面,因為“熱” Observable可能會在subscribe
注冊之前處理該事件。 觀察者將錯過通知,回調將永遠不會觸發,並且測試將無效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.