前置き
Angularの一般的な構成を見ると、app.modules.tsなどのNgModuleで定義するのが一般的です。
しかし、Componentでもprovidersを定義することは可能です。
何故Componentに定義せず、NgModuleで定義するべきなのかという問題を、開発時に遭遇したコードから考察します。
問題のコード
Component内でprovidersを定義していた時、以下のコードで問題が起きました。
@Component({
  selector: 'app-heroes',
  templateUrl: 'foo.component.html',
  providers: [
    HeroService,
  ],
})
export class HeroesComponent {
beforeEach(() => {
  TestBed.configureTestingModule({
    declarations: [
      HeroesComponent,
    ],
    providers: [
      { provide: HeroService, useClass: MockHeroService },
    ],
  });
});
上記のように、テスト時にテストのために作成したモッククラス注入させようとした際にMockHeroServiceの注入をすることに失敗し、Mockの処理を走らせることができませんでした。
なぜ失敗したかというと、 HeroesComponent が見るHeroService はspecで定義したHeroService ではなく、 HeroesComponent で定義した HeroService を参照しにいくからです。
この例から分かるように、 HeroesComponent は HeroService と切り離された関係でなくなり、独立性が損なわれることになります。
まとめ
今回の例から分かるように、Component内にprovidersをして依存性を注入してしまうと、アプリケーションという視点から見た時に関係性の分離ができていないため、DIの本質から逸脱しているというのは明白です。
なので、NgModuleで定義しましょうということです。
Angular 6
というのはAngular4までの話で、Angular6を利用している場合、 @Injectable の providedIn を利用すれば、今回のような過ちは早々起きることもないかと思われます。
明日は、 @Kirika さんが担当します
よろしくお願いします
