@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

上的构造函数可能会出现一些(其他)意外行为