2016-12-03 64 views
2

我有一個select元素在我的模板如下:角2更新選擇在單位更改模型試驗

<select [(ngModel)]="snapshotCriteria.salesArea" required> 
    <option *ngFor="let salesArea of salesAreas" [ngValue]="salesArea"> 
    {{salesArea.name}} 
    </option> 
</select> 

你可以看到,該模型必然會snapshotCriteria.salesArea這是一個對象,所以我們使用ngValue代替value。屬性本身也是一個對象。


的成分如下:

export class Component implements OnInit { 

    salesAreas: SalesArea[]; 

    snapshotCriteria: SnapshotCriteria = { 
    salesArea: null, 
    date: null, 
    startTime: 600, 
    endTime: 3059 
    }; 


    constructor(private salesAreaService: SalesAreaService) {} 


    ngOnInit(): void { 
    this.salesAreaService.fetchSalesAreas(salesAreas) => this.salesAreas = salesAreas); 
    } 

} 

注意,其被綁定到模型selectsalesArea初始化爲null


當通過操作下拉菜單通過模板進行更改時,模板正常運行。但是在我的單元測試中,我直接更新了select元素引用的模型,並且與我期望的相反,視圖沒有更新!由於該字段是必需的,因爲驗證失敗,我的測試無法提交表單。這是測試:

it('...', fakeAsync(() => { 

    spyOn(salesAreaService, 'fetchSalesAreas').and.returnValue(Observable.of([ 
    {areaNumber: 1, name: 'A'} as any as SalesArea, 
    {areaNumber: 2, name: 'B'} as any as SalesArea, 
    {areaNumber: 3, name: 'C'} as any as SalesArea 
    ])); 

    fixture.detectChanges(); 
    tick(); 

    component.snapshotCriteria = { 
    salesArea: {areaNumber: 1, name: 'A'} as SalesArea, 
    date: new Date(2015, 5, 25), 
    startTime: 1000, 
    endTime: 1001 
    } as SnapshotCriteria; 

    fixture.detectChanges(); 
    tick(); 

})); 

調試顯示select元素未更新。我嘗試了各種各樣的東西無濟於事:

  1. 不在測試中重新實例化對象。
  2. 實例化salesArea對象爲空對象而不是 null
  3. 調度inputchange事件在測試中。
  4. 在視圖中聆聽ngModelChange,但在測試中未觸發 。

記下感興趣的是,通過使用模板中valuengValue,我能夠通過改變底層模型更新視圖。

+0

此行爲是相似,我測試了'select'元素的指令時經歷。我不得不做多個'detectChanges'和'whenStable'(我沒有使用'fakeAsync')調用。嘗試再次調用'fixture.detectChanges();蜱();'。 (我爲此提出了一個[問題](https://github.com/angular/angular/issues/11895),但回想起來,我的repro不是基於測試的,而是專注於其他一些奇怪的行爲,我可能會提出另一個更關注測試的問題) – cartant

+0

@cartant在測試過程中,fixture一直保持穩定,給tick()添加更多調用沒有任何作用。 – Cristian

+0

這是重要的多重'detectChanges'調用。這就是爲我解決的。但是,因爲我沒有使用'fakeAsync',所以我和'whenStable'調用進行了配對。 – cartant

回答

2

我認爲你需要做的,如下所示:

it('...', fakeAsync(() => { 
    var mockArr = [ 
    {areaNumber: 1, name: 'A'} as any as SalesArea, 
    {areaNumber: 2, name: 'B'} as any as SalesArea, 
    {areaNumber: 3, name: 'C'} as any as SalesArea 
    ]; 
    spyOn(salesAreaService, 'fetchSalesAreas').and.returnValue(Observable.of(mockArr)); 

    fixture.detectChanges(); 
    tick(); 

    component.snapshotCriteria = { 
    salesArea: mockArr.find(x => x.areaNumber === 1), 
    date: new Date(2015, 5, 25), 
    startTime: 1000, 
    endTime: 1001 
    } as SnapshotCriteria; 

    fixture.detectChanges(); 

    tick(); 
    expect(...); 
})); 

Plunker Example

+1

100%正確,謝謝!看起來'component.snapshotCriteria.salesArea'的值需要是一個引用傳遞給'option'元素'ngFor'的'salesAreas'的對象。 – Cristian