簡體   English   中英

模板中可觀察的最佳測試

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM