【问题标题】:Angular FormBuilder is undefined in unit testsAngular FormBuilder 在单元测试中未定义
【发布时间】:2023-02-17 16:11:56
【问题描述】:

我有以下组件:

.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();
  });
});

如果我尝试运行它,我会收到以下错误:

hrome 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)

如果我将 formControl 初始化移动到构造函数,它会正常工作。但我不想那样做:那样的话我将不得不将我的表单声明为未类型化的FormGroup&lt;any&gt;,因此我将失去它提供的类型安全性(more about this here, "Avoid This Common Typed Forms Pitfall"。

【问题讨论】:

    标签: angular angular-forms angular-formbuilder


    【解决方案1】:

    解决方案是不使用注入的FormBuilder实例,而是创建一个新实例:

    export class TopUpAmountChangeDialogComponent {
      topupAmountFormGroup = new FormBuilder().group({
        topupAmount: [this.data.topupAmount, {
          validators: [
            Validators.required,
            Validators.min(0),
          ]
        }],
      })
    ...
    
    

    它仅在 documentation 中隐式描述,我认为在这种情况下我们应该这样做应该更清楚。

    【讨论】:

      猜你喜欢
      • 2019-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-03
      • 2020-06-19
      • 2018-09-02
      • 2015-06-29
      • 2021-08-04
      相关资源
      最近更新 更多