angularunit-testingng-mocks

Auto-Mock Angular Components


Problem

When testing Angular Components, I often stumble upon the following error message:

'NG0304: 'app-chip' is not a known element:
1. If 'app-chip' is an Angular component, then verify that it is part of this module.
2. If 'app-chip' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.'

Reason

It's usually because I use a Component (here: <app-chip>) in the template:

<div class="asanas-filter">
  <app-filter-sticky-header [optionIds]="['asanas']"> Asanas </app-filter-sticky-header>

  <div class="chips" *ngIf="asanas">
    <app-chip
      *ngFor="let asana of asanas"
      [label]="asana.label"
      [(model)]="model[asana.id]"
    ></app-chip>
  </div>
  <app-filter-footer [optionIds]="['asanas']" [groupOption]="true"></app-filter-footer>
</div>

and forgot to add the mocked Component to the Spec-File:

TestBed.configureTestingModule({
  declarations: [
    AsanasFilterComponent,
    MockComponent(FilterStickyHeaderComponent),
    MockComponent(FilterFooterComponent),
    // MockComponent(AppChipComponent) is missing here
  ],
}).compileComponents();

I am using ng-mocks for mocking Components.

Desired Solution

I think, having to manually add the components used in the template to the Test Config does not benefit the development process: If I forgot to import a component I'm using into the current module (or in case of a typo), the build will fail anyway. (because of that I don't want to use CUSTOM_ELEMENTS_SCHEMA)

Is there a way to automatically add all the components I use in the Template to the declarations-Array as Mocks?

Or is there a reason to not do it (and keep adding them manually)?


Solution

  • what you are looking for is MockBuilder.

    With its help you need only a component and its module, the rest will be mocked automatically by default.

    beforeEach(() => MockBuilder(AsanasFilterComponent, AsanasFilterModule));
    

    if AsanasFilterModule imports / declares FilterStickyHeaderComponent, FilterFooterComponent and AppChipComponent, then they'll be mocked.

    The goal here is the same like avoiding CUSTOM_ELEMENTS_SCHEMA: if a developer has deleted a declaration or an import from AsanasFilterModule, then related tests would fail due to the missing mock in MockBuilder.