How can I fake/mock/spy the a service in component test to avoid the NullInjectorError with Angular 9 / Jasmine / Karma?

Viewed 296

In my Angular app I need to test my component which use a UserService service. This UserService extends the ProxyService which extends RemoteDataService. This RemoteDataService uses HttpClient.

This is the component's code:

@Component({
  selector: 'app-tax-type-list',
  templateUrl: './tax-type-list.component.html',
})
export class TaxTypeListComponent {
  userService = AppModule.InjectorInstance.get<UserService>(UserService);

  constructor() { }

  // ...
}

user.service.ts


@Injectable({
  providedIn: 'root'
})
export class UserService extends ProxyService<UserInterface> {

  constructor() {
    super(new User());
  }

  getCurrentUser(): UserInterface {
    return new User().init(localStorage.getItem('user'));
  }
}

proxy.service.ts


@Injectable({
  providedIn: 'root'
})
export class ProxyService<T> extends RemoteDataService<T> {
  constructor(
    private instance: T,
  ) {
    super(instance);
  }

  // ...
}

remote-data.service.ts

export class DataService<T> {
  private http: HttpClient;

  constructor(model: T) {
    this.http = AppModule.InjectorInstance.get<HttpClient>(HttpClient);
  }
  // ...
}

Here is my test:

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

  // set TestBed before each tests
  beforeAll(async(() => {
    TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
    TestBed.configureTestingModule({
      imports: [
        // angular testing module that provides mocking for http connections
        HttpClientTestingModule,
        RouterTestingModule,
      ],
      // add declaration of services or components and use inject to get to them in tests
      providers: [
        Injector,
        {provide: HelperFactoryService, useValue: new TaxType() },
      ],
      declarations: [
        TaxTypeListComponent,
      ],
    }).compileComponents();

    AppModule.InjectorInstance = TestBed;
    TestBed.inject(HelperFactoryService);
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(TaxTypeListComponent);
    component = fixture.componentInstance;
    component.userService = new UserService();
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

And now I get this error message:

NullInjectorError: R3InjectorError(DynamicTestModule)[UserService -> HttpClient -> HttpClient]:
  NullInjectorError: No provider for HttpClient!
error properties: Object({ ngTempTokenPath: null, ngTokenPath: [ 'UserService', 'HttpClient', 'HttpClient' ] })

How can I fake/mock/spy the UserService to avoid the NullInjectorError?

0 Answers
Related