我正在为包含多个组件的Angular应用程序之一编写单元测试。在我的组件之一(组件A)中,它有一个子组件,如下所示:
组件A
<div class="row row-top">
<div class="col-12">
<app-data-grid
[columnDefs]="columnDefs"
[defaultColDef]="defaultColumnDefs"
[overlayNoRowsTemplate]="overlayNoRowsTemplate"
[hasFloatingFilter]="hasFloatingFilter"
[frameworkComponents]="frameworkComponents"
[rowData]="rowData"
[hasMultipleRows]="rowSelection"
[hasRowAnimation]="hasRowAnimation"
[multiSortKey]="multiSortKey"
(rowDataChanged)="onRowDataChanged()"
(selectionChanged)="onSelectionChanged()"
(rowClicked)="gotoDetailView($event)"
(sortChanged)="onSortChanged($event)"
(columnResized)="onColumnResized()"
(gridReady)="OnGridReady($event)"
>
</app-data-grid>
<div class="float-right">
<button
id="addDevice"
type="button"
class="btn btn-brand btn-primary position-relative add-button"
(click)="gotoAddDevice()"
>
<i class="fa fa-plus"></i>
</button>
</div>
</div>
</div>
如果您在ComponentA中看到上述HTML,则我有 组件,当在Grid中调整列的大小时,该组件将调用函数,这将在ComponentA内部调用onColumnResized(),如下所示>
onColumnResized() {
const updatedColumns: ColumnWidth[] = [];
this.columnApi.getColumnState().forEach((column) => {
updatedColumns.push({ field: column.colId, width: column.width });
});
this.store.dispatch(new DevicesActions.UpdateColumnWidth(updatedColumns));
}
我的问题是我怎么监视 onColumnResized()或直接像下面这样调用该函数
describe('ColumnResized', () => {
it('call the onColumnResized', () => {
expect(component.onColumnResized()).toHaveBeenCalled();
});
});
我想知道这是否正确,我是否可以使用spyOn()代替直接调用该函数
答案 0 :(得分:1)
您不应测试是否调用了该方法。您应该测试在调整子组件大小时该组件的行为是否正确。
有一个很好的库可以模拟您的组件:https://www.npmjs.com/package/ng-mocks
类似的东西:
let columnApiMock: jasmine.SpyObj<ColumnApi>;
beforeEach(() => {
TestBed.configureTestingModule({
...
providers: [
{ provide: YourStoreService,
useValue: jasmine.createSpyObj('YourStoreService', ['dispatch']) },
{ provide: ColumnApi,
useValue: jasmine.createSpyObj('ColumnApi', ['getColumnState']) },
],
declarations: [
AppComponentA, // not mocked
MockComponent(AppDataGrid),
],
});
columnApiMock = TestBed.inject(ColumnApi) as jasmine.SpyObj<ColumnApi>;
})
...
it('test if columns are stored on resize', () => {
// expect you have mocked your colum api, prepare columns that should be returned
columnApiMock.getColumnState.and.returnValue([...]);
const dataGridMock = ngMocks.find(fixture.debugElement, AppDataGrid);
// trigger Output from DataGrid
dataGridMock.columnResized.emit();
expect(TestBed.inject(YourStoreService).dispatch))
.toHaveBeenCalledWith(...);
});
这样,您的测试就不会依赖于组件的内部实现。
您需要知道是否调用了名为onColumnResized
的方法。您必须确保在调整大小时使用正确的列更新商店...
答案 1 :(得分:1)
Nidhin,在提供答案之前,让我解释一下组件的单元测试的意图。
组件的单元测试意味着您应该检查组件的行为(包括HTML和
git add . git commit -m ‘test’ git push
代码)。应该牢记的一个重要因素是“我们应该尽可能地将正在测试的组件与外部依赖项(主要是服务)隔离开”。
恕我直言,您仅应在调用ts
时检查行为是否正常。您不必担心onColumnResized()
是否在app-data-grid
上调用它。在(columnResized)
测试中,您应该测试是否app-data-grid
是否按照预期进行了募集/调用。
注意:作为集成测试的一部分,您应该测试两个组件一起工作的行为,这意味着您要同时测试多个组件的工作情况(集成)
对于您而言,以下代码:
columnResized
您应该执行以下测试:
onColumnResized() {
const updatedColumns: ColumnWidth[] = [];
this.columnApi.getColumnState().forEach((column) => {
updatedColumns.push({ field: column.colId, width: column.width });
});
this.store.dispatch(new DevicesActions.UpdateColumnWidth(updatedColumns));
}
内部的store
设为公开(这样我们就可以通过在组件外部访问它来监视它)constructor
或者您可以简单地覆盖返回类型而无需创建export class MockColumnApi {
getColumnState() {
return [
{colId: 1, column: 2 }
];
}
}
describe('SomeComponent', () => {
let component: SomeComponent;
let fixture: ComponentFixture<SomeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
// whatever you need to import
],
declarations: [SomeComponent, GridComponent],
providers: [
{ provide: ColumnApi, useClass: MockColumnApi },
],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should create dispatch columns on resize call', () => {
spyOn(component.columnApi, 'getColumnState').and.callThrough();
spyOn(component.store, 'dispatch').and.callThrough();
component.onColumnResized();
expect(component.columnApi.getColumnState).toHaveBeenCalled()
expect(component.store.dispatch).toHaveBeenCalledWith(
new DevicesActions.UpdateColumnWidth({colId: 1, column: 2 })
);
});
});
:
MockColumnApi
您可以参考this article of mine,其中我结合了几个主题,作为Angular单元测试教程的一部分。希望对您有所帮助。