Angular 8 单元测试,无法设置 属性 'valueAccessor' 为 null
Angular 8 Unit Test, Cannot set property 'valueAccessor' of null
我试图简单地通过测试 (应该创建 - component=> toBeTruthy) 用于自定义组件(angular 组件 class) 使用 ControlValueAccessor 实现。我在 constructor
中注入了 NgControl 并传递了 this
关键字。
constructor(@Optional() @Self() public controlDir?: NgControl) {
this.controlDir.valueAccessor = this;
}
然后在 ngOnInit()
ngOnInit() {
const control = this.controlDir.control;
const validators = control.validator ? [control.validator] : [];
const asyncValidators = control.asyncValidator ? [control.asyncValidator] : [];
control.setValidators(validators);
control.setAsyncValidators(asyncValidators);
control.updateValueAndValidity();
}
在测试文件中
describe('TextInputComponent', () => {
let component: TextInputComponent;
let fixture: ComponentFixture<TextInputComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TextInputComponent],
imports: [ReactiveFormsModule]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TextInputComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
以及错误
TypeError: Cannot set property 'valueAccessor' of null
如果有人分享您解决此问题的想法,我将不胜感激?
谢谢。
拉宾
您可以像这样创建一个模拟 class NgControl :
export class TestNgControl {
valueAccessor : any = null;
}
然后在providers for configureTestingModule方法中,你可以这样写:
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TextInputComponent],
imports: [ReactiveFormsModule],
providers : [{ provide : NgControl, useClass : TestNgControl}]
})
.compileComponents();
}));
请告诉我这是否有效。
我通过调用包含表单的 <app-text-input formControlName="test"></app-text-input>
模板创建新的模拟 class 组件解决了这个问题。
这里是代码详情:
@Component({
template: `
<form [formGroup]="form">
<app-text-input formControlName="input">
</app-text-input>
</form>`
})
class TestingInput {
@ViewChild(TextInputComponent, { static: true })
textInputComponent: TextInputComponent;
form = new FormGroup({
input: new FormControl('Test Value')
});
}
describe('TextInputComponent', () => {
let component: TextInputComponent;
let fixture: ComponentFixture<TestingInput>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TextInputComponent, TestingInput],
imports: [ReactiveFormsModule]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TestingInput);
component = fixture.componentInstance.textInputComponent;
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
谢谢大家的回答和评论,都没有解决确切的问题,但至少有想法弄清楚。
如果您有任何其他更好的方法来解决此问题,请随时post回答。
非常感谢!
我通过为 controlDir 添加 @Optional 装饰器解决了这个问题,然后在 if 语句中将其赋值给 controlDir.valueAccessor,因为 controlDir 不会在测试中赋值。
constructor(@Self() @Optional() public controlDir: NgControl) {
if (controlDir) {
controlDir.valueAccessor = this;
}
}
然后在您的 ngOnInit() 中,您还需要将任何访问 controlDir 的调用包装在 if 语句中,因为它不会被设置。
ngOnInit() {
if (this.controlDir) {
const control = this.controlDir.control;
const validators = control.validator
? [control.validator, this.validate]
: this.validate;
control.setValidators(validators);
control.updateValueAndValidity();
}
}
有些人在使用上述内容构建产品时遇到问题,并且还使用下面 URL 中的说明解决了您的问题,该说明在测试中使用了 TestbedStatic.overrideComponent。
我试图简单地通过测试 (应该创建 - component=> toBeTruthy) 用于自定义组件(angular 组件 class) 使用 ControlValueAccessor 实现。我在 constructor
中注入了 NgControl 并传递了 this
关键字。
constructor(@Optional() @Self() public controlDir?: NgControl) {
this.controlDir.valueAccessor = this;
}
然后在 ngOnInit()
ngOnInit() {
const control = this.controlDir.control;
const validators = control.validator ? [control.validator] : [];
const asyncValidators = control.asyncValidator ? [control.asyncValidator] : [];
control.setValidators(validators);
control.setAsyncValidators(asyncValidators);
control.updateValueAndValidity();
}
在测试文件中
describe('TextInputComponent', () => {
let component: TextInputComponent;
let fixture: ComponentFixture<TextInputComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TextInputComponent],
imports: [ReactiveFormsModule]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TextInputComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
以及错误
TypeError: Cannot set property 'valueAccessor' of null
如果有人分享您解决此问题的想法,我将不胜感激?
谢谢。 拉宾
您可以像这样创建一个模拟 class NgControl :
export class TestNgControl {
valueAccessor : any = null;
}
然后在providers for configureTestingModule方法中,你可以这样写:
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TextInputComponent],
imports: [ReactiveFormsModule],
providers : [{ provide : NgControl, useClass : TestNgControl}]
})
.compileComponents();
}));
请告诉我这是否有效。
我通过调用包含表单的 <app-text-input formControlName="test"></app-text-input>
模板创建新的模拟 class 组件解决了这个问题。
这里是代码详情:
@Component({
template: `
<form [formGroup]="form">
<app-text-input formControlName="input">
</app-text-input>
</form>`
})
class TestingInput {
@ViewChild(TextInputComponent, { static: true })
textInputComponent: TextInputComponent;
form = new FormGroup({
input: new FormControl('Test Value')
});
}
describe('TextInputComponent', () => {
let component: TextInputComponent;
let fixture: ComponentFixture<TestingInput>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TextInputComponent, TestingInput],
imports: [ReactiveFormsModule]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TestingInput);
component = fixture.componentInstance.textInputComponent;
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
谢谢大家的回答和评论,都没有解决确切的问题,但至少有想法弄清楚。 如果您有任何其他更好的方法来解决此问题,请随时post回答。 非常感谢!
我通过为 controlDir 添加 @Optional 装饰器解决了这个问题,然后在 if 语句中将其赋值给 controlDir.valueAccessor,因为 controlDir 不会在测试中赋值。
constructor(@Self() @Optional() public controlDir: NgControl) {
if (controlDir) {
controlDir.valueAccessor = this;
}
}
然后在您的 ngOnInit() 中,您还需要将任何访问 controlDir 的调用包装在 if 语句中,因为它不会被设置。
ngOnInit() {
if (this.controlDir) {
const control = this.controlDir.control;
const validators = control.validator
? [control.validator, this.validate]
: this.validate;
control.setValidators(validators);
control.updateValueAndValidity();
}
}
有些人在使用上述内容构建产品时遇到问题,并且还使用下面 URL 中的说明解决了您的问题,该说明在测试中使用了 TestbedStatic.overrideComponent。