Angular单元测试中FormBuilder未定义问题及类型安全诉求
Angular组件单元测试报错,需保留表单字段初始化写法以维持类型安全
组件代码 (.ts)
import {Component, Inject} from '@angular/core'; import {FormBuilder, Validators} from '@angular/forms'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {IValueAndCurrency} from '@model/IValueAndCurrency'; @Component({ selector: 'app-top-up-amount-change-dialog', templateUrl: './top-up-amount-change-dialog.component.html', styleUrls: ['./top-up-amount-change-dialog.component.scss'], }) export class TopUpAmountChangeDialogComponent { topupAmountFormGroup = this.fb.group({ topupAmount: [this.data.topupAmount, { validators: [ Validators.required, Validators.min(0), ] }], }) constructor( private dialogRef: MatDialogRef<TopUpAmountChangeDialogComponent>, private fb: FormBuilder, @Inject(MAT_DIALOG_DATA) public data: { topupAmount: IValueAndCurrency; possibleAmounts: IValueAndCurrency[]; }, ) { } }
单元测试代码
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing'; import {TopUpAmountChangeDialogComponent} from './top-up-amount-change-dialog.component'; import {FormBuilder, FormsModule, ReactiveFormsModule} from '@angular/forms'; import {HttpClientModule} from '@angular/common/http'; import {MATERIAL_MODULES} from 'src/app/app.consts'; import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {APP_CONFIG} from "../../../../../../../appConfig.injectortoken"; import {TestAppConfigJson} from "../../../../../../app.component.spec"; import {BrowserAnimationsModule} from "@angular/platform-browser/animations"; import {IValueAndCurrency} from "../../../../../../common/models/IValueAndCurrency"; import {Currency} from "../../../../../../common/models/enums/currency.enum"; fdescribe('TopUpAmountChangeDialogComponent', () => { let component: TopUpAmountChangeDialogComponent; let fixture: ComponentFixture<TopUpAmountChangeDialogComponent>; const matRefSpy = jasmine.createSpyObj('matRefSpy', ['close']); const dialogData: { topupAmount: IValueAndCurrency, possibleAmounts: IValueAndCurrency[] } = { topupAmount: { value: 10, currencyCode: Currency.EUR }, possibleAmounts: [ { value: 0, currencyCode: Currency.EUR }, { value: 0, currencyCode: Currency.USD } ] }; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [ FormsModule, BrowserAnimationsModule, MATERIAL_MODULES, ReactiveFormsModule, HttpClientModule, ], declarations: [TopUpAmountChangeDialogComponent], providers: [ FormBuilder, {provide: APP_CONFIG, useValue: TestAppConfigJson}, {provide: MatDialogRef, useValue: matRefSpy}, {provide: MAT_DIALOG_DATA, useValue: dialogData}, ], }).compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(TopUpAmountChangeDialogComponent); component = fixture.componentInstance; component.data = dialogData; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); });
测试报错信息
Chrome 110.0.0.0 (Linux x86_64) TopUpAmountChangeDialogComponent should create FAILED TypeError: Cannot read properties of undefined (reading 'group') at new TopUpAmountChangeDialogComponent (src/app/modules/.../top-up-amount-change-dialog/top-up-amount-change-dialog.component.ts:12:34)
需求说明
将表单控件初始化逻辑移至构造函数后测试可正常运行,但希望保留当前写法,借助FormBuilder隐式推断类型以维持类型安全,避免手动定义接口造成代码重复。
内容的提问来源于stack exchange,提问作者ForestG
相关产品推荐
相关产品推荐

