我有一个简单的角度分量,如下所示。
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
,但是事实并非如此。请问我做错了什么?任何帮助将不胜感激。
答案 0 :(得分:2)
这是因为component
与您期望的实例不同。在beforeEach
中,您将创建新的CheckBoxComponent
;在it
中,您将创建测试主机组件CustomTestClass
的实例。 Angular创建新的CheckBoxComponent
作为测试主机组件的子代,因此,当您更改主机组件的输入值时,它不会反映在component
实例中。
您应该做的只是创建测试主机组件,然后在该组件中注入CheckBoxComponent
和@ViewChild
并在测试中使用该实例。
代码:
删除.then
中的beforeEach
部分。
编辑测试主机组件:
class CustomTestClass {
checkValue = false;
@ViewChild(CheckBoxComponent) checkBoxComponent: CheckBoxComponent;
}
在测试中将component
替换为testComponent.checkBoxComponent
。