Directive Testing with injected host component

22 Views Asked by At

I have a directive, in which I am getting the component instance via inject keyword like this:

export class MyDirective implements AfterViewInit {
  private component: MyBaseComponent = inject(MyBaseComponent);
  ...
}

MyBaseComponent is an abstract component, from which multiple other controls are derived (e.g. MyTextComponent).
Example usage of MyDirective inside html-template of a component:

<my-text-component my-directive>

So the 'component' property inside 'MyDirective' class is becoming the 'my-text-component'.

The problem is though the unit-testing with jest.
The empty skeleton code for unit-testing looks like that:

describe("MyDirectiveTest", () => {
  let directive: MyDirective;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [MyDirective, MyBaseComponent, MyTextComponent],
      providers: [{ provide: MyBaseComponent, useClass: MyTextComponent }],
    });
    directive = new MyDirective();
  });

  it("should initialize correctly", () => {
    expect(directive).toBeTruthy();
  });
});

I am getting the following error:

NG0203: inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with runInInjectionContext.

And it's showing exactly the code line with the inject() as source of the error.

PS:
Before you suggest adding @injectable() decorator to MyDirective,
I already tried that, besides Directives and Components are injectable per default anyway.

1

There are 1 best solutions below

0
Naren Murali On BEST ANSWER

You need to create a component/ use an existing component to test a directive, a directive cannot be initialized separately, that is why you are getting this error. Instead use TestBed.createComponent(MyTextComponent) to initialize the component and test the directive through the component.

Angular docs for directive testing

NOTE: Since you initialize the directive as a class, it does not have any Angular context. It's just a class, that is why inject is giving you an error.

directive = new MyDirective(); // <- line with the problem!