56

I have a component which receives a component class of component to dynamically create as a child.

let componentFactory = this.componentFactoryResolver.resolveComponentFactory(componentToCreate);
this.componentReference = this.target.createComponent(componentFactory);

I'm trying to write a unit test and pass some TestComponent for it to create & render.

TestBed
  .configureTestingModule(<any>{
    declarations: [MyAwesomeDynamicComponentRenderer, TestHostComponent],
    entryComponents: [TestComponent],
  });

There is casting to "any" because configureTestingModule expects TestModuleMetadata which doesn't have entryComponents but I get error: "No component factory found for TestComponent".

How can I provide the entryComponents to a TestBed?

Pavel Staselun
  • 1,970
  • 1
  • 12
  • 24

2 Answers2

103

You can also do it into your test file directly if you want :

import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing'; // DO not forget to Import

TestBed.configureTestingModule({
  declarations: [ MyDynamicComponent ],
}).overrideModule(BrowserDynamicTestingModule, {
  set: {
    entryComponents: [ MyDynamicComponent ],
  }
});
nircraft
  • 8,242
  • 5
  • 30
  • 46
Alex
  • 4,599
  • 4
  • 22
  • 42
  • 12
    import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing'; in case this helps anyone – johnstaveley Jun 14 '18 at 07:09
  • How would we override the current Module definition `TestBed.configureTestingModule({...})` to include entryComponents? would we have to create the TestModule as suggested in another answer to do this? – Jessy Nov 30 '18 at 15:42
  • @Jessycormier I'm not sure to understand your question. This is basically what I'm doing in the example : I'm calling the overrideModule method and I provide, via the set key, a new array of entryComponents. If you have other components, you can just create an array with it, and set entryComponents like this : `entryComponents: [ ...myComponentArray, MyDynamicComponent ]` ( '...' being the syntax sugar for 'Object.assign()' ) – Alex Dec 03 '18 at 13:20
  • 2
    I think that this is a proper answer for this problem and this should be accepted. – kris_IV Jan 31 '19 at 08:56
  • 1
    I'm getting NullInjector errors when my entryComponent needs providers. – Adam Jenkins Feb 11 '19 at 21:02
  • It worked. This should be the accepted answer. EDIT: For those who are dealing with MatDialog testing issue "no component factory found, did you add it to @NgModule.entryComponents?". – Amel Mahmuzić Nov 10 '19 at 07:42
89

Okay, I figured it out. In the test you should define new module where you declare your mock component and specify it as an entryComponent too.

@NgModule({
  declarations: [TestComponent],
  entryComponents: [
    TestComponent,
  ]
})
class TestModule {}

And import it into TestBed

TestBed
  .configureTestingModule({
    declarations: [ValueComponent, TestHostComponent],
    imports: [TestModule],
  });

I hope it will help someone :]

Pavel Staselun
  • 1,970
  • 1
  • 12
  • 24
  • 1
    If only StackOverflow let you upvote an answer more than once! – Chris Knight Oct 01 '17 at 18:30
  • I prefer this to the accepted answer because it uses the same mechanisms that my production code uses to import NgModules. I also do not need to know what the `overrideModule` method does or doesn't do. – lortimer Oct 31 '20 at 04:02
  • Thanks for the answer, although old. My problem was similar but I was using shallow-renderer for angular. I had to create a testModule and provide an entry component there, which was used in the test component that I was writing. – Sami Nov 16 '21 at 08:19