angulardart/angular

NgTestBed - how to mock transitive, locally provided dependencies

daniel-v opened this issue · 0 comments

  • Dart SDK version: 2.9.1 (stable) (Wed Aug 12 12:37:19 2020 +0200) on "linux_x64"
  • 5.3.1
  • Linux
  • Chrome

Using NgTestBed to test simple components is very convenient. However, as soon as I start working with components that use other components that might depend on locally specified services, I'm in trouble. Let me illustrate:

@Component(
  selector: 'a-cmp',
  template: '<b-cmp></b-cmp>',
  directives: [BComponent],
)
class AComponent {}

@Component(
  selector: 'b-cmp',
  template: 'bbbb',
  providers: [
    ClassProvider(SomeService, useClass: SomeServiceImpl),
  ],
)
class BComponent {
  final ASvc svc;

  BComponent(this.svc) {
    print('${svc.runtimeType}');
  }
}

abstract class SomeService {}

class SomeServiceImpl implements SomeService {}

So the dependency tree looks like so: AComponent -> BComponent -> SomeService. Looking at the generated code for AComponent. Naively, I attempted to mock BComponent's dependency, SomeService.

@GenerateInjector([
  ClassProvider(SomeService, useClass: FakeSvc),
])
final InjectorFactory rootInjector = self.rootInjector$Injector;

// ...
final testBed = NgTestBed.forComponent<AComponent>(ng.AComponentNgFactory, rootInjector: rootInjector);

FakeSvc has never been initialized and this is due to how .template.dart files look:

  ComponentRef<import1.AComponent> build() {
    // ...
    _compView_0 = import2.ViewBComponent0(this, 0);
   // ...
    _SomeService_0_5 = import3.SomeServiceImpl();
    _BComponent_0_6 = import4.BComponent(_SomeService_0_5);
    _compView_0.create0(_BComponent_0_6);
   // ...
  }

My assumption was that dependencies will be, in fact, retrieved from the DI system instead of static imports. It is clear, that as long as instantiation of SomeService happens via imports instead of using DI, my attempt at overriding it in the test will never work.

My question is so: am I limited to testing functionality of components with NgTestBed to components that do not depend on other components? If not, how do I go about resolving the use-case mentioned above?