0

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)?

satanTime
  • 12,631
  • 1
  • 25
  • 73
Florian Gössele
  • 4,376
  • 7
  • 25
  • 49
  • you can use CUSTOM_ELEMENTS_SCHEMA just in tests, then no mocks would be required – Andrei Jan 06 '22 at 14:30
  • @Andrei here it's stated that it's not good practice and I would like to avoid it, if possible: https://stackoverflow.com/a/58699863/2725515 – Florian Gössele Jan 06 '22 at 14:35
  • 1
    my cheap trick is to put a bunch of often used components into a 'common' module and import that in my testingModule. Bad for multiple reasons as you want your unit tests as isolated as possible but other than that, the console should print that as a warning, not an error – scy Jan 06 '22 at 19:32

1 Answers1

1

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.

satanTime
  • 12,631
  • 1
  • 25
  • 73
  • That's really cool! But I found an even better solution (which includes mocking): [shallow-render](https://github.com/getsaf/shallow-render) - I will go with this one. Thanks anyway – Florian Gössele Jan 20 '22 at 20:57