@Input 上的默认值导致测试问题 - angular,摘要 class
Default value on @Input causes test problems - angular, abstract class
我的测试遇到了一些问题。
就我而言,我有 2 个组成部分:
import {Component, Input, OnInit} from '@angular/core';
import {BComponent} from '../b/b.component';
@Component({
selector: 'a',
templateUrl: './a.component.html',
styleUrls: ['./a.component.scss'],
providers: [{provide: BComponent, useExisting: AComponent}]
})
export class AComponent extends BComponent<any> implements OnInit {
@Input() foo = true;
ngOnInit(): void {
super.ngOnInit();
}
}
import {Component, Input, OnInit} from '@angular/core';
import {FormBuilder} from '@angular/forms';
@Component({
template: '',
})
export abstract class BComponent<T> implements OnInit {
@Input() value: T;
constructor(
protected formBuilder: FormBuilder
) {
let a = this.formBuilder.control(null);
}
ngOnInit(): void {
}
}
我的测试是这样的:
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {AComponent} from './a.component';
import { ReactiveFormsModule} from '@angular/forms';
describe('AComponent', () => {
let component: AComponent;
let fixture: ComponentFixture<AComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [AComponent],
imports: [
ReactiveFormsModule],
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(AComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
问题出在 AComponent
中的 @Input() foo = true;
。
一定是默认值和ReactiveFormsModule
.
有问题
错误显示:
AComponent › should create
TypeError: Cannot read property 'control' of undefined
12 | protected formBuilder: FormBuilder
13 | ) {
> 14 | let a = this.formBuilder.control(null);
| ^
15 |
16 | }
17 |
at new BComponent (src/app/testing/brainfuck/b/b.component.ts:14:34)
at new AComponent (src/app/testing/brainfuck/a/a.component.ts:258:5)
at createClass (../packages/core/src/view/provider.ts:273:14)
at createDirectiveInstance (../packages/core/src/view/provider.ts:142:7)
at createViewNodes (../packages/core/src/view/view.ts:314:28)
at createRootView (../packages/core/src/view/view.ts:216:3)
at callWithDebugContext (../packages/core/src/view/services.ts:641:23)
at Object.debugCreateRootView [as createRootView] (../packages/core/src/view/services.ts:121:10)
at ComponentFactory_.Object.<anonymous>.ComponentFactory_.create (../packages/core/src/view/refs.ts:91:27)
at initComponent (../packages/core/testing/src/test_bed.ts:605:28)
at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:407:30)
at ProxyZoneSpec.Object.<anonymous>.ProxyZoneSpec.onInvoke (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:3765:43)
at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:406:56)
at Object.onInvoke (../packages/core/src/zone/ng_zone.ts:405:29)
at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:406:56)
at Zone.Object.<anonymous>.Zone.run (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:167:47)
at NgZone.Object.<anonymous>.NgZone.run (../packages/core/src/zone/ng_zone.ts:184:50)
at TestBedViewEngine.Object.<anonymous>.TestBedViewEngine.createComponent (../packages/core/testing/src/test_bed.ts:609:56)
at Function.Object.<anonymous>.TestBedViewEngine.createComponent (../packages/core/testing/src/test_bed.ts:236:36)
at src/app/testing/brainfuck/a/a.component.spec.ts:20:27
at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:407:30)
at ProxyZoneSpec.Object.<anonymous>.ProxyZoneSpec.onInvoke (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:3765:43)
at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:406:56)
at Zone.Object.<anonymous>.Zone.run (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:167:47)
at Object.wrappedFunc (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:4250:34)
如果我删除默认值,一切正常。
Angular版本为
"@angular/core": "12.0.5",
提前致谢!
当您在 AComponent
上添加默认值 属性 时,它会强制调用继承的构造函数。发生这种情况是因为 class 具有初始值的属性在 Typescript 转译期间被有效地移动到构造函数中
您可能不应该在抽象 class 上有构造函数,但至少您需要通过覆盖 AComponent
中的构造函数来调用它,传递 FormBuilder
作为参数
constructor(
protected formBuilder: FormBuilder
) {
super(formBuilder)
}
注意:我没有机会对此进行测试,但抽象 classes
上的构造函数可能会出现一些(其他)意外行为
我的测试遇到了一些问题。
就我而言,我有 2 个组成部分:
import {Component, Input, OnInit} from '@angular/core';
import {BComponent} from '../b/b.component';
@Component({
selector: 'a',
templateUrl: './a.component.html',
styleUrls: ['./a.component.scss'],
providers: [{provide: BComponent, useExisting: AComponent}]
})
export class AComponent extends BComponent<any> implements OnInit {
@Input() foo = true;
ngOnInit(): void {
super.ngOnInit();
}
}
import {Component, Input, OnInit} from '@angular/core';
import {FormBuilder} from '@angular/forms';
@Component({
template: '',
})
export abstract class BComponent<T> implements OnInit {
@Input() value: T;
constructor(
protected formBuilder: FormBuilder
) {
let a = this.formBuilder.control(null);
}
ngOnInit(): void {
}
}
我的测试是这样的:
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {AComponent} from './a.component';
import { ReactiveFormsModule} from '@angular/forms';
describe('AComponent', () => {
let component: AComponent;
let fixture: ComponentFixture<AComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [AComponent],
imports: [
ReactiveFormsModule],
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(AComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
问题出在 AComponent
中的 @Input() foo = true;
。
一定是默认值和ReactiveFormsModule
.
错误显示:
AComponent › should create
TypeError: Cannot read property 'control' of undefined
12 | protected formBuilder: FormBuilder
13 | ) {
> 14 | let a = this.formBuilder.control(null);
| ^
15 |
16 | }
17 |
at new BComponent (src/app/testing/brainfuck/b/b.component.ts:14:34)
at new AComponent (src/app/testing/brainfuck/a/a.component.ts:258:5)
at createClass (../packages/core/src/view/provider.ts:273:14)
at createDirectiveInstance (../packages/core/src/view/provider.ts:142:7)
at createViewNodes (../packages/core/src/view/view.ts:314:28)
at createRootView (../packages/core/src/view/view.ts:216:3)
at callWithDebugContext (../packages/core/src/view/services.ts:641:23)
at Object.debugCreateRootView [as createRootView] (../packages/core/src/view/services.ts:121:10)
at ComponentFactory_.Object.<anonymous>.ComponentFactory_.create (../packages/core/src/view/refs.ts:91:27)
at initComponent (../packages/core/testing/src/test_bed.ts:605:28)
at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:407:30)
at ProxyZoneSpec.Object.<anonymous>.ProxyZoneSpec.onInvoke (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:3765:43)
at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:406:56)
at Object.onInvoke (../packages/core/src/zone/ng_zone.ts:405:29)
at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:406:56)
at Zone.Object.<anonymous>.Zone.run (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:167:47)
at NgZone.Object.<anonymous>.NgZone.run (../packages/core/src/zone/ng_zone.ts:184:50)
at TestBedViewEngine.Object.<anonymous>.TestBedViewEngine.createComponent (../packages/core/testing/src/test_bed.ts:609:56)
at Function.Object.<anonymous>.TestBedViewEngine.createComponent (../packages/core/testing/src/test_bed.ts:236:36)
at src/app/testing/brainfuck/a/a.component.spec.ts:20:27
at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:407:30)
at ProxyZoneSpec.Object.<anonymous>.ProxyZoneSpec.onInvoke (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:3765:43)
at ZoneDelegate.Object.<anonymous>.ZoneDelegate.invoke (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:406:56)
at Zone.Object.<anonymous>.Zone.run (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:167:47)
at Object.wrappedFunc (node_modules/zone.js/bundles/zone-testing-bundle.umd.js:4250:34)
如果我删除默认值,一切正常。
Angular版本为
"@angular/core": "12.0.5",
提前致谢!
当您在 AComponent
上添加默认值 属性 时,它会强制调用继承的构造函数。发生这种情况是因为 class 具有初始值的属性在 Typescript 转译期间被有效地移动到构造函数中
您可能不应该在抽象 class 上有构造函数,但至少您需要通过覆盖 AComponent
中的构造函数来调用它,传递 FormBuilder
作为参数
constructor(
protected formBuilder: FormBuilder
) {
super(formBuilder)
}
注意:我没有机会对此进行测试,但抽象 classes
上的构造函数可能会出现一些(其他)意外行为