javascript - Angular Reactive Form Unit Testing:HTML 值和控件值不同步
问题描述
我在此处遵循 Angular 反应式表单单元测试指南,但始终无法获取控制值和 HTML 值以进行同步。下面是我的实现;setValue
请注意,除了指定默认值之外,我还尝试调用:
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {
loginForm!: FormGroup;
constructor(private formBuilder: FormBuilder) { }
ngOnInit(): void {
this.initLoginForm();
const usernameControl = this.loginForm.get('username');
usernameControl?.valueChanges.subscribe(username => {
debugger; // This doesn't fire
this.loginForm.patchValue({username: username});
});
}
initLoginForm() {
this.loginForm = this.formBuilder.group({
username: ['jack', Validators.compose([Validators.required])],
password: ['JacksPassword']
});
this.loginForm.setValue({
username: 'jack',
password: 'JacksPassword'
})
this.loginForm.updateValueAndValidity();
}
}
<form [formGroup]="loginForm" id="loginForm">
<div>
<input formControlName="username" placeholder="Username" required id="usernameInput"/>
</div>
<div>
<input formControlName="password" placeholder="Password" type="password"/>
</div>
</form>
这是我的测试:
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormBuilder } from '@angular/forms';
import { UserComponent } from './user.component';
describe('UserComponent', () => {
let component: UserComponent;
let fixture: ComponentFixture<UserComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [UserComponent],
providers: [FormBuilder]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(UserComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should have same values between control and UI', () => {
const loginFormUserElement: HTMLInputElement = fixture.debugElement.nativeElement.querySelector('#loginForm').querySelector('#usernameInput');
const userNameValueFromGroup = component.loginForm.get('username');
expect(loginFormUserElement.value).toEqual(userNameValueFromGroup?.value);
});
it('should accept username', () => {
const loginFormUserElement: HTMLInputElement = fixture.debugElement.nativeElement.querySelector('#loginForm').querySelector('#usernameInput');
loginFormUserElement.value = 'joe';
loginFormUserElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
fixture.whenStable().then(() => {
const userNameValueFromGroup = component.loginForm.get('username');
expect(loginFormUserElement.value).toEqual('joe');
expect(loginFormUserElement.value).toEqual(userNameValueFromGroup?.value);
});
});
});
这是结果。设置默认值不会更新 UI。调用setValue
不会更新 UI。并且在 UI 元素上设置值不会更新控件。
它必须是基本的东西。我错过了什么?
编辑:我试图建立一个基于独立单元测试示例的 StackBlitz 实现,但formGroup
在 Jasmine 下似乎无法识别该指令;我正在导入ReactiveFormsModule
app.module。链接在这里,以防任何人都可以提供有关我在这方面所缺少的内容的见解。
编辑:这里的问题似乎实际上与我的单元测试工作有关。当我直接使用组件时,默认值会正确显示在 HTML 输入元素上;但是,在运行 Karma 的 Chrome 上通过控制台检查消息时,我看到相同的错误消息,表明该formGroup
指令无法识别。我已经相应地更新了标题。
解决方案
问题实际上纯粹是在单元测试的设置中,当组件被实时使用时,控件和表单之间的绑定工作正常。单元测试中的问题是ReactiveFormsModule
必须通过导入TestBed.configureTestingModule
;我也没有ngOnInit
在设置过程中打电话,尽管它的缺席似乎没有任何影响(还)。
我更新的设置代码如下。奇怪的是,尝试ReactiveFormsModule
在 StackBlitz 设置中以相同的方式导入会产生错误“超出最大调用堆栈大小”,但它在我的机器上运行良好。
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TimeRangeSelectorComponent],
imports: [ReactiveFormsModule], // This is new
providers: [
FormBuilder,
{ provide: TimeRangeSelectorDefaultsBase, useValue: new TestTimeRangeSelectorDefaults() },
]
});
fixture = TestBed.createComponent(TimeRangeSelectorComponent);
component = fixture.componentInstance;
component.ngOnInit(); // This is new
fixture.detectChanges();
});
原来这是一个骗局。把这个问题留在这里,以防它帮助别人;在我开始搜索与测试相关的问题之前,我没有发现另一个。
推荐阅读
- python - 在 Pandas 数据框中按 MinMaxScaler 分组
- assembly - 涉及 ESP 的寻址模式?
- vue.js - vue.js 3 / 根据 REST API 调用更改 VueApexCharts 图例
- flutter - Flutter URL 策略在 Web Release 上不起作用
- python - 如何在 Python 中的 Django 日历上创建“删除事件”按钮
- javascript - AngularFirestore 权限缺失或不足(Firebase 自定义令牌身份验证)
- python - 编写一个程序,在平面上输入三个点,它必须决定它们是否创建一个三角形,以及它们是否创建哪种类型
- ghostscript - 在 ubuntu 上运行 makefile 安装 ghostscript 时出错
- sql - 正则表达式仅用双引号替换第一个分号
- python - 从深度数组中提取列表