Angular 5测试:如何获取对子组件的引用

Bee*_*ice 24 unit-testing angular

我正在尝试测试Angular应用程序中主机组件和子组件之间的交互.我不知道如何获取对父元素创建时创建的子组件的引用.这是设置:

child.component.spec.ts

@Component({template: `<child [data]="model"></child>`})
class HostComponent {
  public model:any;
}

describe('ChildComponent', () => {
  let hostFixture: ComponentFixture<HostComponent>;
  let childFixture: ComponentFixture<ChildComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ChildComponent, HostComponent]
    });
  }));

  beforeEach(() => {
    // this creates the child component as well, but how to get to it?
    hostFixture = TestBed.createComponent(HostComponent);

    // this creates a NEW instance of child component, not the one from the Host template
    // so it's not the instance I actually want to test
    childFixture = TestBed.createComponent(ChildComponent);
  });
});
Run Code Online (Sandbox Code Playgroud)

更改modelhostFixture.componentInstance实际上并不会改变data输入值childFixture.componentInstance; 这就是我如何意识到有两个子组件实例.

我的问题很简单,我如何才能childFixture参考HostComponent模板中找到的组件夹具,而不是像我现在拥有的那样引用不同的实例?

文档没有帮助.

Est*_*ask 51

指南所述,主机组件实例是使用创建的TestBed.createComponent,并且可以debugElement使用By帮助程序从中选择子组件实例:

childDebugElement = hostFixture.debugElement.query(By.directive(ChildComponent));
Run Code Online (Sandbox Code Playgroud)

要么:

childDebugElement = hostFixture.debugElement.query(By.css('child'));
Run Code Online (Sandbox Code Playgroud)

  • 它不是模板元素.这是https://angular.io/api/core/DebugElement.您可以使用`childDebugElement.componentInstance`获取实例. (17认同)
  • 你的代码不会给我一个 debugElement 吗?我正在尝试获取组件实例本身,而不是模板元素。 (3认同)
  • 我想访问组件属性。对我来说,`childDebugElement.context`在这里起到了作用。+1引导我找到解决方案。谢谢! (2认同)
  • 如果其他人有问题,那么“按”就不可用了,这是import语句:`import {By} from'@ angular / platform-b​​rowser';` (2认同)

Ste*_*cks 12

上面的答案很好,回答了正文的问题,但问题的标题/标题提出了其他问题。我也想回答标题提出的问题。Estus 的答案对于特定用例是正确的,但 Google 会根据标题中的问题将您带到这里。

要获取子组件而不是本机元素:

测试组件(在问题中称为 HostComponent): <child [data]="model" #child></child>

然后在类定义中:

@Component({template: `<child #child [data]="model"></child>`})
class HostComponent {
    public model:any;
    @ViewChild('child') child;
}
Run Code Online (Sandbox Code Playgroud)

最后,在测试时,在规范上:

it('should do something', () => {
    component.child.value
    component.child.method
    // etc.
}
Run Code Online (Sandbox Code Playgroud)

您可以在测试用例中使用它,我也这样做,以找到您真正要测试的子组件。


剩下的就是满足评论中提出的一个有争议的方面。

在可能的情况下,也有充分的理由将事情设为私有。如果你想对它进行单元测试,我不确定我的感受。如果你想测试一个私有成员,你必须让你想要的带有私有成员的对象的打字稿编译器可以公开访问,方法是将其强制转换为并将其包装在括号中,以明确你在转换什么。

在组件中:

...
    @ViewChild('child') private child;
...
Run Code Online (Sandbox Code Playgroud)

在测试中:

...
    (<any>component).child.value
    (<any>component).child.method
...
Run Code Online (Sandbox Code Playgroud)