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

时间:2017-12-13 15:24:04

标签: angular unit-testing

我正在尝试测试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);
  });
});

更改model中的hostFixture.componentInstance值实际上并未更改data的{​​{1}}输入值;这就是我如何意识到有两个子组件实例。

我的问题很简单,如何让childFixture.componentInstance引用childFixture模板中的组件夹具,而不是我目前拥有的其他实例?

The docs没有帮助。

3 个答案:

答案 0 :(得分:39)

the guide中所述,主机组件实例是使用TestBed.createComponent创建的,并且可以从debugElement By helper中选择子组件实例:

childDebugElement = hostFixture.debugElement.query(By.directive(ChildComponent));

或者:

childDebugElement = hostFixture.debugElement.query(By.css('child'));

答案 1 :(得分:3)

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

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

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

然后在类定义中:

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

最后,在进行测试时,请遵循以下规范:

it('should do something', () => {
    component.child.value
    component.child.method
    // etc.
}

您可以在测试用例中使用它,而我确实可以找到您真正要测试的子组件。


剩下的就是要满足评论中值得商aspect的方面。

在可能的情况下,也有很强的理由将事情保密。如果您要对它进行单元测试,我不确定我的想法。如果要测试私有成员,则必须通过将其强制转换为类型并将其包装在括号中以使其清晰可见,从而使具有私有成员的对象的打字稿编译器可公开访问。

在组件中:

...
    @ViewChild('child') private child;
...

在测试中:

...
    (<any>component).child.value
    (<any>component).child.method
...

答案 2 :(得分:1)

遍历debugElement的childNodes并访问context属性以获得对组件及其属性的访问权限

let debugElement = hostFixture.debugElement.childNodes[x] as DebugElement
debugElement = debugElement.childNodes[x] as DebugElement
...
let component = debugElement.context as YourComponent

这是一种非常静态的方法,因为如果添加了新的子节点,则可能访问错误的childNode。最好编写一个遍历childNode并找到正确名称的辅助方法。