Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding logging hint "Did you mean to use componentProviders instead of providers" when createComponentFactory is misconfigured in jest tests #618

Open
Exac opened this issue Jun 22, 2023 · 1 comment

Comments

@Exac
Copy link

Exac commented Jun 22, 2023

Description

Hi everyone,

I ran into some trouble this morning because I incorrectly setup my test. I provided a mock of my service in providers instead of componentProviders, so the real service was called during my tests.

The error message I received was something like:

    NullInjectorError: R3InjectorError(DynamicTestModule)[SomeUnexpectedService -> SomeOtherService -> ThirdUnexpectedService -> FourthUnexpectedService -> FifthUnexpectedService]: 
      NullInjectorError: No provider for FifthUnexpectedService!

Example:

import 'zone.js/dist/zone';
import { Component, inject, Injectable } from '@angular/core';
import { CommonModule } from '@angular/common';
import { bootstrapApplication } from '@angular/platform-browser';

@Injectable()
export class MyService {
  doSomething(): string {
    console.log('Calling real API');
    return 'real';
  }
}

@Component({
  selector: 'my-app',
  standalone: true,
  imports: [CommonModule],
  providers: [MyService],
  template: `
    <p>Value is {{ value | json }}</p>
  `,
})
export class App {
  constructor(private readonly myService: MyService) {}
  public value = this.myService.doSomething();
}

bootstrapApplication(App);
import { CommonModule } from '@angular/common';
import { Spectator } from '@ngneat/spectator';
import { createComponentFactory, mockProvider } from '@ngneat/spectator/jest';
import { of } from 'rxjs';
import { App, MyService } from 'src/main';

describe('App', () => {
  let spectator: Spectator<App>;

  const createComponentWithCorrectProviderMock = createComponentFactory({
    component: App,
    shallow: true,
    componentProviders: [
      mockProvider(MyService, {
        doSomething: jest.fn().mockReturnValue('mocked'),
      }),
    ],
    imports: [CommonModule],
  });

  const createComponentWithWrongProvider = createComponentFactory({
    component: App,
    shallow: true,
    providers: [
      mockProvider(MyService, {
        doSomething: jest.fn().mockReturnValue(of('mocked')),
      }),
    ],
    imports: [CommonModule],
  });

  test('passing test', () => {
    spectator = createComponentWithCorrectProviderMock();
    expect(spectator.component.value).toEqual('mocked');
  });

  test('failing test', () => {
    spectator = createComponentWithWrongProvider();
    // This will use the real provider, because we incorrectly
    // use `providers`, instead of `componentProviders`.
    expect(spectator.component.value).toEqual('mocked');
  });
});

Proposed solution

I think it would be very helpful if we were able to provide a hint to the developer here to check if their service is provided in providers instead of componentProviders.

Alternatives considered

I am not sure if this is possible with spectator, or if this would have to be done in Jest? I filed the issue here, because the providers vs componentProviders is declared in SpectatorOptions.

Do you want to create a pull request?

No

@stackblitz
Copy link

stackblitz bot commented Jun 22, 2023

Fix this issue in StackBlitz Codeflow Start a new pull request in StackBlitz Codeflow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant