如何对以 TemplateRef 作为输入的 Angular 组件进行单元测试?

Aje*_*orf 7 unit-testing typescript karma-jasmine angular2-template angular

我正在尝试为 Angular 组件编写单元测试,它可以隐藏/显示作为输入传递给组件本身的一些内容。预期的输入定义为 TemplateRef。

我的component.component.ts

@Component({
    selector: "my-component",
    templateUrl: "./my-component.component.html",
    styleUrls: ["./my-component.component.scss"],
    exportAs: "mycomponent"
})
export class MyComponent {
    private _expanded = false;

    @Input()
    set expanded(value: boolean) {
        this._expanded = value;
    }

    @Input()
    body: TemplateRef<any>;
    @Input()
    handler: TemplateRef<any>;

    constructor() {}

    toggleView() {
        this.expanded = !this._expanded;
    }
}

Run Code Online (Sandbox Code Playgroud)

我的component.component.html

<div class="wrap">
    <!-- Header -->
    <main #header>
        <header (click)="toggleAccordion()">
            <div class="handler">
                <ng-container [ngTemplateOutlet]="handler">
                </ng-container>
            </div>
            <i class="icon icon-expand" [ngClass]="{ 'icon-expand': _expanded, 'icon-collapse': !_expanded }"></i>
        </header>
    </main>
    <!-- Body -->
    <div class="body" *ngIf="_expanded">
        <ng-container [ngTemplateOutlet]="body"></ng-container>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

我想测试通过输入“body”传递的内容是否可见,但我无法弄清楚如何在 jasmine 中使用 TemplateRef 输入实例化“我的组件”。

Angular 文档解释了如何在单元测试脚本上传递输入,但是由于 TemplateRef 是一个抽象类,我无法实例化任何 TemplateRef 对象,我不知道如何管理它。

我的component.component.spec.ts

<div class="wrap">
    <!-- Header -->
    <main #header>
        <header (click)="toggleAccordion()">
            <div class="handler">
                <ng-container [ngTemplateOutlet]="handler">
                </ng-container>
            </div>
            <i class="icon icon-expand" [ngClass]="{ 'icon-expand': _expanded, 'icon-collapse': !_expanded }"></i>
        </header>
    </main>
    <!-- Body -->
    <div class="body" *ngIf="_expanded">
        <ng-container [ngTemplateOutlet]="body"></ng-container>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

Sha*_*vek 10

我会尽量给你一个演示代码,你可以进一步扩展

基本上,您需要以不同的方式对此进行测试。由于您无法在不使用TemplateRef其他组件的情况下创建组件,因此您需要创建一个包装组件并通过为 WrapperComponent 编写测试用例来测试您的组件


@Component({
  template: `
    <ng-template #div1>Something here</ng-template>
    <ng-template #div2>Many things here</ng-template>
    <my-component [expanded]="expandedVal" [body]="div1" [handler]="div2"> </my-component>
  `,
})
class WrapperComponent {
     @ViewChild(MyComponent) appComponentRef: MyComponent;
     public expandedVal = true;
}

describe('MyComponent', () => {
  let app: MyComponent;
  let fixture: ComponentFixture<WrapperComponent>;
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [WrapperComponent, MyComponent],
    }).compileComponents();
  }));
  beforeEach(() => {
    fixture = TestBed.createComponent(WrapperComponent);
    const wrapperComponent = fixture.debugElement.componentInstance;
    app = wrapperComponent.appComponentRef; // this is where you get "MyComponent" component for testing
    fixture.detectChanges();
  });
  it('should create the app', async(() => {
    expect(app).toBeDefined();
  }));
});
Run Code Online (Sandbox Code Playgroud)

  • 我最初无法让上面的例子工作。我必须像这样“@ViewChild(ChildComponent, { static: true })”声明 ViewChild 才能使其工作。这意味着子级在更改检测发生之前解析,在示例中发生在将组件分配给测试属性之后。 (2认同)