【问题标题】:How to properly get child component instance in Angular unit test?如何在 Angular 单元测试中正确获取子组件实例?
【发布时间】:2022-06-11 06:26:15
【问题描述】:

我正在使用 Angular 中的 karma 编写单元测试,但我正在努力解决奇怪的问题。我正在尝试测试app-source-roll-history-form 的输出取消,它位于source-roll-history.dialog.ts 内部。为了实现这一点,我需要子组件的实例。当我试图获取它时,父组件实例被返回,而不是子组件实例。

source-roll-history-dialog.html

  <ng-template #newRollContent>
    <app-source-roll-history-form
      (save)="assignNewRoll$.next($event)"
      (cancel)="newAssignmentForm = false">
    </app-source-roll-history-form>
  </ng-template>

source-roll-history-dialog.spec.ts

  it('should show/hide form to assign new roll', () => {
  ...
    const instance = fixture.debugElement.query(By.css('app-source-roll-history-form')).componentInstance;
    console.log(fixture.debugElement.query(By.css('app-source-roll-history-form')));
    console.log(instance);
  });

console.log(fixture.debugElement.query(By.css('app-source-roll-history-form'))); 给了我这样的调试元素:

&lt;app-source-roll-history-form _ngcontent-a-c295=""&gt;&lt;/app-source-roll-history-form&gt;

所以没关系。但是当我试图获取这个组件的实例时:

fixture.debugElement.query(By.css('app-source-roll-history-form')).componentInstance

我正在获取父级实例:

SourceRollsHistoryDialogComponent{actions$: Actions{_subscribe: observer => { ... }}, toasterService: ToasterService{toastrService: ToastrService{overlay: ...,

【问题讨论】:

  • 我看到 app-source-roll-history-form 组件位于带有 newRollContent 模板引用变量的 ng-template 中。这不是用于 if / else 吗?也许您只是没有正确模拟单元测试中的数据,以便呈现 app-source-roll-history-form
  • 我试图将它移到 ng-template 之外,但仍然相同,所以情况并非如此,但它在 matDialog 内部,可能与 angular Material 有一些问题?
  • 如果组件在 matDialog 中呈现,异步方面可能是原因。如果在对话框中渲染组件涉及动画,也许您应该尝试使用 fixture.whenStable 或类似的东西(等待组件在对话框中呈现)“捕捉”组件
  • 您能解释一下您要测试的内容吗?如果您期望基于组件的自然接口(输入、输出、用户界面、后端 API)而不是检查内部,测试会更稳定。如果您使用不同的方法,您可能不需要访问组件实例。
  • @slim 如果在子组件 (app-source-roll-history-form) 发出输出取消后,我想在父组件 (source-roll-history-dialog) 内部进行测试 - newAssignmentForm 变量为 false ,所以应该隐藏表单。所以我需要 app-source-roll-history-form 的实例来输出他的输出。

标签: angular karma-jasmine


【解决方案1】:

免责声明:这个答案并没有解释如何获取子组件的实例,但它提供了解决背后问题的其他方法。

在问题中,需要子组件的组件实例来触发子组件的输出事件。这可以通过不同的方式完成:

  1. 使用用户界面触发取消事件,即执行用户必须执行的任何操作来触发此事件。 (可能这意味着在某处单击取消按钮?这将是我的首选解决方案。)

或者如果您不想与子组件交互(例如,因为它的设置太复杂):

  1. 使用像ngMocks 这样的模拟库来模拟子组件和emit an event from the mocked child。这也使您不必在 TestBed 中声明或提供子组件的依赖项。

【讨论】:

    猜你喜欢
    • 2021-01-05
    • 1970-01-01
    • 2020-02-03
    • 1970-01-01
    • 2014-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多