Komponen anak uji unit sudut
Saya menulis unit test untuk salah satu aplikasi Angular saya yang terdiri dari beberapa komponen. Di salah satu komponen saya (Komponen A), ia memiliki komponen anak seperti di bawah ini
Komponen 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>
Jika Anda melihat HTML di atas di KomponenA saya mengalami komponen yang memanggil fungsi ketika kolom diubah ukurannya di Grid yang akan memanggil onColumnResized () di dalam ComponentA saya seperti di bawah ini
onColumnResized() {
const updatedColumns: ColumnWidth[] = [];
this.columnApi.getColumnState().forEach((column) => {
updatedColumns.push({ field: column.colId, width: column.width });
});
this.store.dispatch(new DevicesActions.UpdateColumnWidth(updatedColumns));
}
Pertanyaan saya adalah bagaimana cara memata-matai onColumnResized () atau dapatkah saya memanggil fungsinya secara langsung seperti di bawah ini
describe('ColumnResized', () => {
it('call the onColumnResized', () => {
expect(component.onColumnResized()).toHaveBeenCalled();
});
});
Saya ingin tahu apakah ini adalah pendekatan yang benar serta dapatkah saya menggunakan spyOn () daripada memanggil fungsi secara langsung
Jawaban
Nidhin, sebelum saya memberikan jawaban izinkan saya menjelaskan maksud pengujian unit untuk suatu komponen.
Pengujian unit komponen berarti Anda harus memeriksa perilaku (yang mencakup HTML &
tskode) komponen. Satu faktor penting yang harus diingat adalah bahwa "kita harus mengisolasi komponen (yang sedang diuji) dari ketergantungan eksternal (kebanyakan layanan) sebanyak mungkin"
IMHO, Anda hanya perlu memeriksa apakah perilaku tersebut berfungsi saat onColumnResized()dipanggil. Anda tidak perlu khawatir apakah app-data-gridakan menelepon atau tidak (columnResized). Dalam app-data-gridpengujian, Anda harus menguji apakah columnResizeddinaikkan / dipanggil sesuai harapan.
Catatan: Anda harus menguji perilaku kedua komponen yang bekerja bersama sebagai bagian dari pengujian Integrasi , yang berarti Anda menguji kerja beberapa komponen secara bersamaan ( terintegrasi )
Dalam kasus Anda, untuk kode di bawah ini:
onColumnResized() {
const updatedColumns: ColumnWidth[] = [];
this.columnApi.getColumnState().forEach((column) => {
updatedColumns.push({ field: column.colId, width: column.width });
});
this.store.dispatch(new DevicesActions.UpdateColumnWidth(updatedColumns));
}
Anda harus melakukan tes di bawah ini:
- Jadikan
storebagian dalamconstructorsebagai publik (agar kita dapat memata-matai dengan mengaksesnya di luar komponen)
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 })
);
});
});
ATAU Anda dapat dengan mudah mengganti tipe pengembalian tanpa membuat MockColumnApi:
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', () => {
const sampleData = [
{colId: 1, column: 2 }
];
spyOn(component.columnApi, 'getColumnState').and.returnValue(sampleData );
spyOn(component.store, 'dispatch').and.callThrough();
component.onColumnResized();
expect(component.columnApi.getColumnState).toHaveBeenCalled()
expect(component.store.dispatch).toHaveBeenCalledWith(
new DevicesActions.UpdateColumnWidth(sampleData )
);
});
});
Anda dapat merujuk artikel saya ini di mana saya telah menggabungkan beberapa topik sebagai bagian dari tutorial pengujian Unit di Angular. Saya harap ini membantu.
Anda sebaiknya tidak menguji apakah metode tersebut dipanggil. Anda harus menguji apakah komponen berperilaku benar saat komponen anak diubah ukurannya.
Ada pustaka yang bagus untuk mengejek komponen Anda: https://www.npmjs.com/package/ng-mocks
Sesuatu seperti itu:
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(...);
});
Dengan cara ini pengujian Anda tidak bergantung pada implementasi internal komponen Anda.
Anda perlu tahu apakah sebuah metode bernama onColumnResizeddipanggil. Anda harus memastikan, bahwa toko Anda diperbarui dengan kolom yang benar ketika terjadi perubahan ukuran ...