6

I have an Angular app with Jest and all tests are working just fine. A component injects a service:

component.ts:

import { FooService } from '../../services/foo.service'; // relative import

constructor(private foo: FooService) {}

component.spec.ts:

import { FooService } from '@services/foo.service'; // alias import

describe('FooComponent', () => {
  let component: FooComponent;
  let fixture: ComponentFixture<FooComponent>;

  beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
      imports: [....],
      providers: [ { provide: FooService, useValue: { bar: () => {} } ],
      declarations: [FooComponent],
      schemas: [NO_ERRORS_SCHEMA]
    })
    .compileComponents();
    ....   
  }));
});

Where both imports refer to the same foo.service.ts, but using different form of import: TypeScript alias vs relative path.

Alias is defined in tsconfig.json:

"paths": {
  "@services/*": ["./app/services/*"]
}

And Jest config:

"moduleNameMapper": {
  "@services/(.*)": "<rootDir>/src/app/services/$1"
}

I have switched to nx workspace and the test started to fail with an error saying that there is no provider for FooService:

NullInjectorError: R3InjectorError(DynamicTestModule)[FooService -> FooService]: 
  NullInjectorError: No provider for FooService!

I have managed to fix it using same form of import - both the service and the test must use either alias import or relative import.

I would like to understand what is the problem here. It looks like Angular/Jest is making injection token / dependency resolvement based on TypeScript path (in Nx workspace). Is there any explanation how this works?

Felix
  • 3,999
  • 3
  • 42
  • 66
  • Can you also post the code for the spec? Also, make sure that the tsconfig being used to run the specs is extending the one in which you've defined the module name mapping. – 31piy Mar 23 '21 at 11:09
  • Just to ensure that nothing else is broken, you can try to mock the service in the test, i.e. `{ provide: FooService, useValue: () => {} }`. It actually shouldn't matter to Angular from where you're importing the service, as long as it satisfies the type requirements. – 31piy Mar 23 '21 at 11:15
  • @31piy I have updated the question with more test initialization logic, but I think there is no problem in here - it relates to the typescript import itself. – Felix Mar 23 '21 at 11:18
  • Do you have path aliases defined in `tsconfig.spec.json`? – mat.hudak Mar 23 '21 at 12:54
  • @dallows - yes I have defined aliases - as I wrote the test work with alias or with relative path but both imports (component and spec) must be same. – Felix Mar 23 '21 at 13:07
  • We had the same issue where stubbing providers did not work. This seems to be rather an issue with jest/ts-jest as we were able to reproduce this even without Angular. In our case defining a moduleNameMapper did actually help and resolved this issue so you may have faced another issue. – Marcus Krahl Mar 08 '23 at 16:24

0 Answers0