1

Problem Description: While writing karma/jasmine unit tests for angular component, which uses other angular components, I have to recursively import all the components included in child components, in testbed configuration. Is there a way that I only have to import direct children of the component under test.

Example Code:

Parent Component Template: (top-most-parent.component.html)

<h1>This is topmost parent in the current example. It has children components</h1>
<app-direct-child #scheduleEditor 
    [param1]="val1" [param2]="val2"></app-direct-child>

Direct Child Component Template: (app-direct-child.component.html):

<h1>This is first direct child in the current example. It itself has children 
components</h1>
<app-grand-child
    [aparam1]="ap1val" [aparam2]="ap2val"></app-grand-child>

Grand Child Component Template: (app-grand-child.component.html):

<h1>This is third level child in the current example</h1>
<p-radioButton name="dummyName" value="dummyVal" [label]="'testing"
                       [(ngModel)]="myModel" (onClick)="myOnClick()"
                       class="field-input"></p-radioButton>

The Question: In the above sample codes, while writing the test cases (spec.ts) file for topmost parent component, I have to import the components used in the children and grand children components. Like in the above example, while writing the test cases for top-most-parent.component, I have to import app-grand-child.component and p-radioButton, which are not directly related to the component under test. spec file is as follows

top-most-parent.component.spec.ts: Please see my questions in the code comments below

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { BrowserModule, Title } from '@angular/platform-browser';
import { Observable } from 'rxjs/Observable';

import { DirectChildComponent } from './direct-child.component';
import { GrandChildComponent } from './grand-child.component';
import { RadioButtonModule } from 'primeng/primeng';

describe('TopMostParentComponentTestSuite', () => {
  let component: TopMostParentComponent;
  let fixture: ComponentFixture<TopMostParentComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        TopMostParentComponent,
        DirectChildComponent, // I understand, this is used by the current component under test, so this should be declared
        GrandChildComponent // But why this is needed? Is there a way this can be avoided ?
        ],

      imports: [
        RadioButtonModule // Also this is being used by grand child component, why is this import needed, is there a way this can be avoided?
      ]
    }).compileComponents();

  fixture = TestBed.createComponent(TopMostParentComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();
  }));

  it('should be created', () => {
    expect(component).toBeTruthy();
  });
});
Aqeel Ashiq
  • 1,988
  • 5
  • 24
  • 57
  • Possible duplicate of [Component declaration in spec files as opposed to loading the top-level module into TestBed](https://stackoverflow.com/questions/46726564/component-declaration-in-spec-files-as-opposed-to-loading-the-top-level-module-i) – Estus Flask Oct 24 '17 at 20:03
  • See also https://stackoverflow.com/a/44396005/3731501 – Estus Flask Oct 24 '17 at 20:05

1 Answers1

2

You need to assign your fixture and component into a seperated beforeEach. As bellow

describe('TopMostParentComponentTestSuite', () => {
  let component: TopMostParentComponent;
  let fixture: ComponentFixture<TopMostParentComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        TopMostParentComponent,
        DirectChildComponent, // I understand, this is used by the current component under test, so this should be declared
        GrandChildComponent // But why this is needed? Is there a way this can be avoided ?
        ],

      imports: [
        RadioButtonModule // Also this is being used by grand child component, why is this import needed, is there a way this can be avoided?
      ]
    }).compileComponents();

  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(TopMostParentComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
  }));

  it('should be created', () => {
    expect(component).toBeTruthy();
  });
});

Also if you do unit testing you need only to test your component. This way you can add to your TestBed.configureTestinModule

  schemas: [ NO_ERRORS_SCHEMA ],
Bo Vandersteene
  • 601
  • 7
  • 16