How to inject a Service that takes an injection token and test it using testbed.inject in Angular 9?

Viewed 768

I recently migrated my application from Angular8 to Angular 9. For all the services that were injected, changing Testbed.get(service) to Testbed.inject(service) was working fine.

However, in case of a service takes a String injectionToken like Testbed.get('StringToken') am getting a lot of errors.

Original setup :

//appModule.ts
providers: [
    {
      provide: 'ApiService',
      useClass: ApiService
    },
//api.service.ts
@Injectable()
export class ApiService implements ApiServiceInterface {

  private baseUrl: string;

  constructor(
    private http: HttpClient,
    private appConfigService: AppConfigService,
  ) {
    this.baseUrl = this.appConfigService.baseUrl();
  }

Another service in which I am injecting APIsevice

//xyz.service.ts
export class XYZService {


  constructor(
    @Inject('ApiService') private apiService: ApiServiceInterface,
    private configurationService: ConfigurationService,
  ) {
 
  }

when I use testbed.get in my spec file, everything is fine but I get a warning that Testbed.get is depreciated.

//xyz.service.spec.ts
describe('XYZService', () => {
  let configurationService: ConfigurationService;
  let apiService: ApiServiceInterface;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        HttpClientModule,
        TranslateModule.forRoot(),
        AppTestingModule
      ],
    });
    configurationService = TestBed.inject(ConfigurationService);
    cacheService = TestBed.inject(CacheService);
    apiService = Testbed.get('ApiService');
  });

As per the angular documentation, I created an InjectionToken in a separate file and imported it everywhere. This is the new setup

//token.ts
import { InjectionToken } from '@angular/core';
import { ApiService } from './app/services/api/api.service';

export const TOKEN1 = new InjectionToken<ApiService>('ApiService');

//appModule.ts
providers: [
    {
      provide: TOKEN1,
      useClass: ApiService
    },
//xyz.service.ts
export class XYZService {


  constructor(
    @Inject(TOKEN1) private apiService: ApiServiceInterface,
    private configurationService: ConfigurationService,
  ) {

  }
//xyz.service.spec.ts
describe('XYZService', () => {
  let configurationService: ConfigurationService;
  let apiService: ApiServiceInterface;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        HttpClientModule,
        TranslateModule.forRoot(),
        AppTestingModule
      ],
    });
    configurationService = TestBed.inject(ConfigurationService);
    cacheService = TestBed.inject(CacheService);
    apiService = Testbed.inject(TOKEN1); //Throws a lot of errors
  });

Seems like the service is not initiated and none of the tests are running. Am I missing something on my end?

1 Answers

in your tesbed, add either of these providers

providers: [
 { provide: SomeToken, useValue: someMockObjectHere },
 { provide: 'someString', useValue: anotherMockObject },
]

then inject them using either

apiService = Testbed.inject<any>(SomeToken);
apiService = Testbed.inject<any>('someString');
Related