angulartypescriptangular-testing-libraryng-mocks

How to render `<ng-container *ngTemplateOutlet="someTemplate" />` when using testing library and MockBuilder?


We use the testing library and MockBuilder from ng-mocks to write unit tests for angular components:

...
<ng-container *ngTemplateOutlet="previewContent" />
...

<!-- Preview Content -->
<ng-template #previewContent>
  <p data-testid="test-text">template is here :)</p>
</ng-template>

and in the component.spec.ts:

function setupBuilder() {
  return MockBuilder(SomeComponent);
}

async function setup(inputs: {
  // inputs...
}) {
  const builder = setupBuilder();
  const utils = await render(SomeComponent, {
    ...builder.build(),
    inputs,
  });
  const user = userEvent.setup();

  utils.debug();

  return { ...utils, user, component: utils.fixture.componentInstance };
}

describe('SomeComponent', () => {
  it('should render', async () => {
    const { component } = await setup({ ... });
    expect(component).toBeDefined();
    expect(screen.getByTestId('test-text')).toBeInTheDocument();
  });

However, this fails, and the debug logging shows that the template is not included in the rendered DOM.


Solution

  • Finally I found the reason and the solution: MockBuilder automatically mocks all things that the component uses, including the NgTemplateOutlet directive... So when I modify my setupBuilder to keep this, it works as expected:

    function setupBuilder() {
      return MockBuilder(SomeComponent)
        .keep(NgTemplateOutlet); // <== important if I want the directive to work
    }