visible true

技術的なメモを書く

daggerで引数のあるコンストラクタを持つModuleをincludesして使う

概要

例えば以下の様なModuleがあったとして(injectsとかは省略している)、

@Module(library = true)
public class AppModule {
  Context context;
  public AppModule(Context context) {
    this.context = context;
  }
  @Provides
  public Context provideContext() {
    return context;
  }
  @Provides
  @Singleton
  public OkHttpClient provideOkHttpClient() {
    return new OkHttpClient();
  }
}

テストで以下の様なModuleを作るとする。

@Module(
    injects = HogeTest.class,
    includes = AppModule.class,
    overrides = true)
class TestModule {
  @Provides
  @Singleton
  public OkHttpClient provideOkHttpClient() {
    return Mockito.mock(OkHttpClient.class);
  }
}

でテストの所でObjectGraphを初期化しようと以下の様に書くと、

@Before
public void before() {
  ObjectGraph graph = ObjectGraph.create(new TestModule());
  graph.inject(this);
}

実行時にエラーが出る。

java.lang.UnsupportedOperationException: No no-args constructor on AppModule$$ModuleAdapter

確かにAppModuleのContextを引数に取るコンストラクタはどこからも呼ばれる感じがしない。そもそもContextを解決できないし。

解決

答えは簡単で、ObjectGraph.create()でAppModuleのインスタンスを渡してやればよい。

@Before
public void before() {
  ObjectGraph graph = ObjectGraph.create(
      new TestModule(),
      new AppModule(Robolectric.application));
  graph.inject(this);
}

まとめ

dagger難しい。