【发布时间】:2018-09-05 05:36:00
【问题描述】:
我有一个简单的角度组件,如下所示。
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,但事实并非如此。请问我在做什么错?任何帮助将不胜感激。
【问题讨论】:
标签: angular unit-testing karma-runner