0

I'm facing a Catch-22 involving the use of Angular's @Inject('Window') in a web API service. When it's used with the Window injection in the service constructor, the test specs fail in the Jasmine/Karma environment as dependency injection fails for Window. If the @Inject isn't included, the test specs succeed, but running the code in localhost causes the same dependency injection error.

@Injectable({
  providedIn: 'root'
})
export class ApiService {

  constructor(@Inject('Window') private w: Window) {...

In the test spec file, I'm mocking the Window object like this to set a custom location:

describe('ApiService', () => {
  let service: ApiService;
  let fakeW: Window;

  beforeEach(waitForAsync(() => {
    fakeW = <any> {
      location: <any> new URL("https://test.environment.com/")
    };

    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [
        { provide: Window, useFactory: () => fakeW },
      ]
    });
    service = TestBed.inject(ApiService);

With the @Inject statement in the constructor, dependency injection fails:

ApiService should create FAILED
        Failed: R3InjectorError(DynamicTestModule)[ApiService -> Window -> Window]:
          NullInjectorError: No provider for Window!
        error properties: Object({ ngTempTokenPath: null, ngTokenPath: [ 'ApiService', 'Window', 'Window' ] })
        NullInjectorError: R3InjectorError(DynamicTestModule)[ApiService -> Window -> Window]:
          NullInjectorError: No provider for Window!

Removing the @Inject from the constructor and just using private w: Window causes tests to succeed. However, it causes the same provider error when the code is run in localhost.

Do I just need to change how I'm mocking the Window object so that @Inject can work with it?

  • Does your original module (ApiModule/AppModule) have provider for window? – esperant Apr 06 '23 at 18:56
  • Window is provided in app.module.ts, in the list of providers with ApiService. providers: [ ApiService, { provide: 'Window', useValue: window} ] ) – Carter Smith Apr 06 '23 at 19:24

1 Answers1

0

I think you have to do:

// Add single quotes to Window because it is an injection token.
{ provide: 'Window', useFactory: () => fakeW },

Check this answer out for more details: https://stackoverflow.com/a/70535517/7365461

AliF50
  • 16,947
  • 1
  • 21
  • 37