问题描述
我正在使用以下代码通过在Angular应用程序中使用Jasmine进行单元测试。
test.component.html:
<p-treeTable [value]="employees" [columns]="cols" class="employeestreetable">
<ng-template pTemplate="header" let-columns>
<tr>
<th *ngFor="let col of cols" style="width:30px">
{{col.header}}
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
<tr [ttRow]="rowNode">
<td width="30" class="text-right" ttEditableColumn>
<p-treeTabletoggler [rowNode]="rowNode">
</p-treeTabletoggler>
<p-treeTableCellEditor>
<ng-template pTemplate="input">
<input type="text" pInputText [(ngModel)]="rowData['name']" />
</ng-template>
<ng-template pTemplate="output">
<input type="text" pInputText [(ngModel)]="rowData['name']">
</ng-template>
</p-treeTableCellEditor>
</td>
<td width="30" class="text-right">
<p-treeTableCellEditor>
<ng-template pTemplate="input">
<input type="text" pInputText [(ngModel)]="rowData['salary']" (ngModelChange)="calculatetotalSalary(rowNode)" />
</ng-template>
<ng-template pTemplate="output">
<input type="text" pInputText [(ngModel)]="rowData['salary']">
</ng-template>
</p-treeTableCellEditor>
</td>
<td width="30" class="text-right" ttEditableColumn>
<p-treeTableCellEditor>
<ng-template pTemplate="input">
<input type="text" pInputText [(ngModel)]="rowData['incentive']" (ngModelChange)="calculatetotalSalary(rowNode)" />
</ng-template>
<ng-template pTemplate="output">
<input type="text" pInputText [(ngModel)]="rowData['incentive']">
</ng-template>
</p-treeTableCellEditor>
</td>
<td width="30" class="text-right">
<span>{{rowData['totalsalary']}}</span>
</td>
</tr>
</ng-template>
</p-treeTable>
test.component.ts:
import { Component,OnInit,ViewChild } from '@angular/core';
import { TreeNode } from 'primeng/primeng'
import { ChangeDetectorRef } from '@angular/core';
@Component({
selector: 'test-app',templateUrl: './test.component.html',styleUrls: ['./test.component.css']
})
export class TestComponent {
cols = [
{ field: 'name',header: 'Name' },{ field: 'salary',header: 'Salary' },{ field: 'incentive',header: 'Incentive' },{ field: 'totalsalary',header: 'Total Salary' }
];
employees: TreeNode[] = [
{
"data": {
"name": "Alex","salary": 10000,"incentive": 5000,"totalsalary": 15000
},"children": [
{
"data": {
"name": "George","salary": 8000,"incentive": 2000,"totalsalary": 10000
},}
]
},{
"data": {
"name": "Robert","salary": 18000,"incentive": 10000,"totalsalary": 280000
},"children": [
{
"data": {
"name": "John","salary": 7000,"totalsalary": 12000
}
}
]
}
];
calculatetotalSalary(rownode) {
rownode.node.data.totalsalary = +rownode.node.data.salary + +rownode.node.data.incentive;
}
}
test.component.spec.ts:
import { async,ComponentFixture,fakeAsync,inject,Testbed,tick } from '@angular/core/testing';
import { HttpClientTestingModule,HttpTestingController } from '@angular/common/http/testing';
import {
TestComponent
} from "./test.component";
import { FormsModule,NgModel } from '@angular/forms';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { MessageService } from 'primeng/api';
import { TreeNode } from 'primeng/api';
import { TreeTableModule } from 'primeng/treetable';
import { By } from '@angular/platform-browser';
import { InputTextModule } from 'primeng/inputtext';
describe('TestComponent',() => {
let component: TestComponent;
let fixture: ComponentFixture<TestComponent>;
let httpClient: HttpClient;
let httpTestingController: HttpTestingController;
beforeEach(async(() => {
Testbed.configureTestingModule({
imports: [ HttpClientTestingModule,FormsModule,TreeTableModule,InputTextModule
],declarations: [ TestComponent ],providers: [ ],schemas: [NO_ERRORS_SCHEMA]
})
.compileComponents();
}));
beforeEach(() => {
fixture = Testbed.createComponent(TestComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
beforeEach(fakeAsync(() => {
fixture = Testbed.createComponent(TestComponent);
component = fixture.componentInstance;
fixture.detectChanges();
tick();
}));
it('should update total salary amount',fakeAsync(() => {
spyOn(component,'calculatetotalSalary');
const editableTreeTableEl = fixture.debugElement.query(By.css(".employeestreetable"));
let editableColumns = editableTreeTableEl.queryAll(By.css(".ui-editable-column input"));
const el = editableColumns[0].nativeElement;
const ngModel = editableColumns[0].injector.get(NgModel);
tick();
ngModel.valueAccessor.writeValue(25000);
el.dispatchEvent(new Event('input'));
fixture.detectChanges();
expect(component.calculatetotalSalary).toHaveBeenCalled(); //failing here
expect(+el.value).toEqual(25000);
}));
});
演示: https://stackblitz.com/edit/test-jasmine-karma-t7khzp?file=app%2Ftest.component.html
我正在更新上述单元测试用例中的薪水金额。当我从上述单元测试用例中更新ngModel值时,如何触发相关的ngModelChange事件?
解决方法
尝试一下:
it('should update total salary amount',fakeAsync(() => {
spyOn(component,'calculateTotalSalary');
const editableTreeTableEl = fixture.debugElement.query(By.css(".employeestreetable"));
let editableColumn = fixture.debugElement.query(By.css(".ui-editable-column input")).nativeElement;
editableColumn.value = 25000;
editableColumn.dispatchEvent(new Event('input'));
fixture.detectChanges();
tick(); // maybe you were missing this tick
expect(component.calculateTotalSalary).toHaveBeenCalled(); // should hopefully pass now
}));