gpt4 book ai didi

angular - 测试包含自定义表单控件的 Angular 组件?

转载 作者:太空狗 更新时间:2023-10-29 18:28:46 28 4
gpt4 key购买 nike

我有一个简单的 Angular 组件,如下所示。

import { Component, Input, forwardRef, ViewEncapsulation } from "@angular/core";
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from "@angular/forms";

export const CUSTOM_CHECKBOX_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CheckBoxComponent),
multi: true
};

@Component({
selector: "checkbox",
templateUrl: "./checkBox.component.html",
styleUrls: ["./checkBox.component.scss"],
providers: [CUSTOM_CHECKBOX_CONTROL_VALUE_ACCESSOR],
encapsulation: ViewEncapsulation.None
})
export class CheckBoxComponent implements ControlValueAccessor {
@Input() name: string;
// Placeholders for the callbacks which are later provided
// by the Control Value Accessor
private innerValue: any = "";
private onTouchedCallback: () => void = () => { };
private onChangeCallback: (_: any) => void = () => { };

// get and set accessor----------------------
get value(): any {
return this.innerValue;
}
set value(v: any) {
if (v !== this.innerValue) {
this.innerValue = v;
this.onChangeCallback(v);
}
}

// From ControlValueAccessor interfaces--------------
writeValue(value: any): void {
if (value !== this.innerValue) {
this.innerValue = value;
}
}
registerOnChange(fn: any): void { this.onChangeCallback = fn; }
registerOnTouched(fn: any): void { this.onTouchedCallback = fn; }
}

我正在为 编写单元测试。我的测试如下所示

    import { CheckBoxComponent, CUSTOM_CHECKBOX_CONTROL_VALUE_ACCESSOR } from "./checkBox.component";
import { TestBed, async, ComponentFixture, fakeAsync, tick } from "@angular/core/testing";
import { DebugElement, Component } from "@angular/core";
import { By } from "@angular/platform-browser";
import { FormsModule } from "@angular/forms";
import { CommonModule } from "@angular/common";

@Component({
selector: "tac-checkbox",
template: `<checkbox name="checkboxId1" label="Checkbox Label" [(ngModel)] = "checkValue" > `,
})
class CustomTestClass {
checkValue = false;
}

describe("Component: CheckBoxComponent", () => {
let component: CheckBoxComponent;
let fixture: ComponentFixture<CheckBoxComponent>;
let testComponent: CustomTestClass;
let testFixture: ComponentFixture<CustomTestClass>;

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [FormsModule, CommonModule],
declarations: [CheckBoxComponent, CustomTestClass],
providers: [CUSTOM_CHECKBOX_CONTROL_VALUE_ACCESSOR],
}).compileComponents().then(() => {
fixture = TestBed.createComponent(CheckBoxComponent);
component = fixture.componentInstance;
component.name = "checkbox";
});
}));

it("...", fakeAsync(() => {
testFixture = TestBed.createComponent(CustomTestClass);
testComponent = testFixture.componentInstance;

fixture.detectChanges();
const onChangeEvent = (change: any) => { console.log("There were changes ", change); };
const registerOnChangeMock = spyOn(component, "registerOnChange").and.callThrough();
const registerOnTouchedMock = spyOn(component, "registerOnTouched").and.callThrough();
const onMockWriteValue = spyOn(component, "writeValue").and.callThrough();

component.registerOnChange(onChangeEvent);

component.registerOnTouched(onChangeEvent);

testComponent.checkValue = !testComponent.checkValue;
fixture.detectChanges();
testFixture.detectChanges();
tick();
fixture.whenStable().then(() => {
expect(registerOnChangeMock).toHaveBeenCalledTimes(1); //pass
expect(registerOnTouchedMock).toHaveBeenCalledTimes(1);
//pass
expect(onMockWriteValue).toHaveBeenCalled(); //failed
expect(testComponent.checkValue).toEqual(component.value); //failed
});
}));

});

根据我上面的测试,我希望 component.value 等于 testComponent.value。但是这失败了,我的问题是考虑我更改了 testComponent 值,难道不应该更新控件值吗?我还期望每当我更改 testComponent 值时调用 writeValue,但事实并非如此。请问我做错了什么?任何帮助将不胜感激。

最佳答案

这是因为 component 与您期望的实例不同。在 beforeEach 中,您正在创建新的 CheckBoxComponent,在 it 中,您正在创建测试主机组件 CustomTestClass 的实例。 Angular 会创建新的 CheckBoxComponent 作为测试主机组件的子组件,因此当您更改主机组件的输入值时,它不会反射(reflect)在 component 实例中。

您应该做的是只创建测试主机组件,并在该组件中注入(inject) CheckBoxComponent@ViewChild,并在测试中使用该实例。

代码:

移除beforeEach中的.then部分。

编辑您的测试主机组件:

class CustomTestClass {
checkValue = false;
@ViewChild(CheckBoxComponent) checkBoxComponent: CheckBoxComponent;
}

在您的测试中将 component 替换为 testComponent.checkBoxComponent

关于angular - 测试包含自定义表单控件的 Angular 组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52177746/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com