首页 > 解决方案 > Angular selectRootElement 适用于应用程序而不是测试

问题描述

我的 Angular 应用程序要求通过以下方式将数据传递给页面上的根组件:

    <application-root testVar="hello world"></application-root>

经过大量研究,我决定不使用 ElementRef 来访问该属性,而是使用 Renderer2。我的 AppComponent 的构造函数设置如下:

    @Component({
      selector: 'application-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.scss']
    })
    export class AppComponent implements OnInit {
      public data: string;
      constructor(private renderer: Renderer2)
      {
        this.data = this.renderer.selectRootElement('application-root', true).getAttribute('testVar');
      }
      ..
    }

当我在我的应用程序中运行它时,我没有收到任何错误,并且我得到了值“hello world”。但是,当我尝试运行单元测试用例时,出现以下错误:“选择器“application-root”与任何元素都不匹配”。这是我的测试用例:

    describe('AppComponent', () => {
      beforeEach(async(() => {
      TestBed.configureTestingModule({
        imports: [
          RouterTestingModule,
          HttpClientTestingModule
        ],
        declarations: [
          AppComponent
        ],
        providers: [
          {provide: Router, useValue: routerSpy},
          Renderer2
        ]
      }).compileComponents();
      fixture = TestBed.createComponent(AppComponent);
      component = fixture.componentInstance;
      }));
      it('should create the app', () => {
        expect(fixture).toBeTruthy();
      });

现在,如果我将 selectRootElement 调用移出构造函数,并移入 ngOnInit() 函数,我的单元测试用例通过,但是当我尝试运行应用程序时,我得到一个空白屏幕。

我需要在我的代码中做什么才能访问可以在我的应用程序中正确运行并通过单元测试用例的根组件属性?

标签: angularattributesangular-renderer2

解决方案


所以我想出的解决方案是将所有内容从构造函数中移出并放入 ngOnInit() 函数中。当我重新测试运行应用程序时,它确实有效,屏幕上没有任何内容。然而,为了使这与单元测试用例一起工作,我了解到我必须在 beforeEach 函数中添加元素本身。

当 Angular 使用 AppComponent 执行其单元测试用例时,被渲染的模板是一个标签,而不是我们都知道的选择器。因此,为了让应用程序获取该元素,我们将首先创建它,然后为该元素设置属性,这样当测试脚本运行时,它将识别模板中的该元素:

    let appElement: ElementRef;
    let renderer2: Renderer2;
    describe('AppComponent', () => {
      beforeEach(async(() => {
      TestBed.configureTestingModule({
        imports: [
          RouterTestingModule,
          HttpClientTestingModule
        ],
        declarations: [
          AppComponent
        ],
        providers: [
          {provide: Router, useValue: routerSpy},
          Renderer2
        ]
      }).compileComponents();
      fixture = TestBed.createComponent(AppComponent);
      renderer2 = fixture.componentRef.injector.get<Renderer2>(Renderer2 as Type<Renderer2>);
      appElement = renderer2.createElement('application-root');
      renderer2.appendChild(fixture.nativeElement, appElement);
      component = fixture.componentInstance;
      }));
      it('should create the app', () => {
        expect(fixture).toBeTruthy();
      });

如果有更好的方法来解决这个问题,我会全力以赴。


推荐阅读