【发布时间】:2020-04-22 00:09:36
【问题描述】:
我有一个研讨会编辑组件(按顺序):
- 构建表单
- 检索要编辑的创意工坊
- 使用创意工坊值更新表单值
代码如下:
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 被调用,但没有像它必须做的那样推动一个组。
我重复一遍,但在实际应用中它按预期工作。
【问题讨论】:
-
在
updateFormValues就在第一行之前,在它之后执行console.log(this.form)和debugger。使用fit运行测试并立即打开开发人员工具(按 F12)。debugger应该被触发,您可以在控制台中看到this.form的值。从错误消息来看,我敢打赌this.form在那个时候是未定义的。在您的测试中直接调用updateFormValues之前,可能没有调用buildForms。 -
this.form与this.discussesForm不同。在我的测试中,第一次期望通过,所以这意味着buildForm被调用。我无法使用浏览器(仅 cli)打开测试,因此调试它有点困难。 -
对不起,我误解了。
-
我会找到一种使用浏览器或某种调试方法进行调试的方法,以便使此类任务更容易。但我想我知道问题出在哪里。在您的测试中,您正在监视
addDiscussion。这只会为该函数创建一个“观察者”,而不是实际调用它的实现。要同时拥有“观察者”并调用该函数,您可以使用spyOn(component, 'addDiscussion').and.callThrough()。其实你可以去掉这个spyOn,我觉得你不需要。 -
哦,我使用 spyOn 来测试 hasBeenCalledTimes(2) 但我现在不再需要它了,你说得对。
标签: angular jasmine karma-jasmine angular-unit-test