由于未定义 FormArray 控件而必须定义控件,因此 UT 未通过
UT not pass due to undefined FormArray control while the control must be defined
我有一个创意工坊编辑组件(按顺序):
- 构建表单
- 检索要编辑的创意工坊
- 使用创意工坊值更新表单值
代码如下:
ngOnInit() {
this.buildForms();
this.initialize();
}
async initialize(): Promise<void> {
const id = this.route.snapshot.params.id;
this.workshop = await this.workshopService.find(id); // in real this is in a trycatch block
this.updateFormValues();
}
buildForms(): void {
this.form = ... // not important, this is not the problem
this.discussesForm = this.formBuilder.group({
array: this.formBuilder.array([], Validators.required),
});
}
updateFormValues(): void {
this.form.patchValue(this.workshop);
this.workshop.ListDebates.forEach((discussion, index) => {
this.addDiscussion();
(this.discussesForm.get('array') as FormArray).at(index).patchValue({ // This line will throw error while UT.
title: discussion.Title, description: discussion.Description, key: discussion.Key,
});
});
}
addDiscussion(): void {
(this.discussesForm.get('array') as FormArray).push(this.formBuilder.group({
title: [null],
description: [null],
key: [null],
});
}
workshop.ListDebates 看起来像:
[
{
Key: 1,
Title: 'title',
Description: 'description',
},
]
所以,上面的所有代码都可以正常工作,但我正在尝试对 updateFormValues 方法进行单元测试。
这是我试过的:
it('should update form values', () => {
spyOn(component, 'addDiscussion');
component.workshop = { Title: 'fake title', ListDebates: [
{ Key: 1, Title: 'fake', Description: 'fake' },
{ Key: 2, Title: 'fake', Description: 'fake' },
]} as any as IColabEvent;
component.updateFormValues();
expect(component.form.value.Title).toEqual('fake title'); // test OK
expect((component.discussesForm.get('array') as FormArray).controls.length).toEqual(2); // test KO, expected 0 to be 2
expect((component.discussesForm.get('array') as FormArray).at(0).value).toEqual(...); // test KO (not runned)
});
每次出现错误:无法读取未定义的 属性 'patchValue'(在 updateFormValues 方法中)。
我尝试了很多东西(以及随机的东西,比如添加 fixture.detectChanges()),但我找不到修复它的方法。
奇怪的是addDiscussion被调用了2次,所以我想知道为什么我的FormArray控件是未定义的。
我已经 console.log() 做了一些事情,看起来 addDiscussion 被调用了,但并没有像它必须做的那样推动一个小组。
我重复一遍,但在实际应用中它按预期工作。
不是您的测试用例有问题,实际上是您的代码有问题。您无需先使用 addDiscussion
创建具有 null
值的对象,然后使用 patchValue
设置值。相反,在您创建表单组本身时设置值。更改 addDiscussion
函数以接受 discussion
参数。
addDiscussion(discussion = {}): void {
this.discussesForm.get('array').push(this.formBuilder.group({
title: discussion.Title || null,
description: discussion.Description || null,
key: discussion.Key || null
}));
}
然后在 updateFormValues
中,在 foreach
循环中,去掉 patchValue
代码并传递 discussion
。
this.workshop.ListDebates.forEach(discussion => {
this.addDiscussion(discussion);
});
除此之外,正如评论中已经提到的,addDiscussion
不再需要被监视,因为您的测试依赖于它。完成后,您的测试应该可以正常工作了。
我有一个创意工坊编辑组件(按顺序):
- 构建表单
- 检索要编辑的创意工坊
- 使用创意工坊值更新表单值
代码如下:
ngOnInit() {
this.buildForms();
this.initialize();
}
async initialize(): Promise<void> {
const id = this.route.snapshot.params.id;
this.workshop = await this.workshopService.find(id); // in real this is in a trycatch block
this.updateFormValues();
}
buildForms(): void {
this.form = ... // not important, this is not the problem
this.discussesForm = this.formBuilder.group({
array: this.formBuilder.array([], Validators.required),
});
}
updateFormValues(): void {
this.form.patchValue(this.workshop);
this.workshop.ListDebates.forEach((discussion, index) => {
this.addDiscussion();
(this.discussesForm.get('array') as FormArray).at(index).patchValue({ // This line will throw error while UT.
title: discussion.Title, description: discussion.Description, key: discussion.Key,
});
});
}
addDiscussion(): void {
(this.discussesForm.get('array') as FormArray).push(this.formBuilder.group({
title: [null],
description: [null],
key: [null],
});
}
workshop.ListDebates 看起来像:
[
{
Key: 1,
Title: 'title',
Description: 'description',
},
]
所以,上面的所有代码都可以正常工作,但我正在尝试对 updateFormValues 方法进行单元测试。
这是我试过的:
it('should update form values', () => {
spyOn(component, 'addDiscussion');
component.workshop = { Title: 'fake title', ListDebates: [
{ Key: 1, Title: 'fake', Description: 'fake' },
{ Key: 2, Title: 'fake', Description: 'fake' },
]} as any as IColabEvent;
component.updateFormValues();
expect(component.form.value.Title).toEqual('fake title'); // test OK
expect((component.discussesForm.get('array') as FormArray).controls.length).toEqual(2); // test KO, expected 0 to be 2
expect((component.discussesForm.get('array') as FormArray).at(0).value).toEqual(...); // test KO (not runned)
});
每次出现错误:无法读取未定义的 属性 'patchValue'(在 updateFormValues 方法中)。
我尝试了很多东西(以及随机的东西,比如添加 fixture.detectChanges()),但我找不到修复它的方法。
奇怪的是addDiscussion被调用了2次,所以我想知道为什么我的FormArray控件是未定义的。
我已经 console.log() 做了一些事情,看起来 addDiscussion 被调用了,但并没有像它必须做的那样推动一个小组。
我重复一遍,但在实际应用中它按预期工作。
不是您的测试用例有问题,实际上是您的代码有问题。您无需先使用 addDiscussion
创建具有 null
值的对象,然后使用 patchValue
设置值。相反,在您创建表单组本身时设置值。更改 addDiscussion
函数以接受 discussion
参数。
addDiscussion(discussion = {}): void {
this.discussesForm.get('array').push(this.formBuilder.group({
title: discussion.Title || null,
description: discussion.Description || null,
key: discussion.Key || null
}));
}
然后在 updateFormValues
中,在 foreach
循环中,去掉 patchValue
代码并传递 discussion
。
this.workshop.ListDebates.forEach(discussion => {
this.addDiscussion(discussion);
});
除此之外,正如评论中已经提到的,addDiscussion
不再需要被监视,因为您的测试依赖于它。完成后,您的测试应该可以正常工作了。