Friday, 18 June 2021

Dagger not creating DaggerTestAppComponent.Test

I'm trying to run an end-to-end test on an app that uses Dagger and Room, When I run the app Dagger isn't able to generate DaggerTestAppComponent.create().

I've been following the [Dagger codelab][1] to implement the Dagger into the tests.

Step 1. Custom Test Runner User a custom test runner to use a different application class.

class MyCustomTestRunner : AndroidJUnitRunner() {

    override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application {
        return super.newApplication(cl, MyTestApplication::class.java.name, context)
    }
}

Step 2 add to app build gradle. The custom test runner is specified in the app build Gradle.

testInstrumentationRunner "com.example.endtoend.dagger.MyCustomTestRunner"

Step 3 load Modules TestAppComponent, used to load different modules in Dagger.


@Singleton
@Component(modules = [TestSaveDataStorageModule::class, RoomModule::class, DispatchersModule::class])
interface TestAppComponent : AppComponent {
    @Component.Factory
    interface Factory {
        fun create(@BindsInstance context: Context): AppComponent
    }
}

Step 4 Add dependencies. In order to generate DaggerTestAppComponent The kapt needs to act on the androidTest folder.

dependencies {
    ...
    kaptAndroidTest "com.google.dagger:dagger-compiler:$dagger_version"
}

step 6 update application MyApplication

open class MyApplication : Application() {
    val appComponent: AppComponent by lazy {
        initializeComponent()
    }
    open fun initializeComponent(): AppComponent {
        return DaggerAppComponent.factory().create(applicationContext)
    }
}

Step 7 TestApplication

class TestApplication : MyApplication() {

    override fun initializeComponent(): AppComponent {
        return DaggerTestAppComponent.create()
    }
}

After following allow those steps I run a test and Dagger generates the DaggerTestAppComponent but it doesn't generate a create() creating an unresolved reference in the code.

DaggerTestAppComponent

@SuppressWarnings({
    "unchecked",
    "rawtypes"
})
public final class DaggerTestAppComponent implements TestAppComponent {
  private Provider<MyRepository> myRepositoryProvider;

  private Provider<Context> contextProvider;

  private Provider<MyDatabase> provideDatabaseProvider;

  private Provider<ItemDao> provideDaoProvider;

  private Provider<RoomRepository> roomRepositoryProvider;

  private Provider<CoroutineDispatcher> providesIoDispatcherProvider;

  private Provider<MainViewModel> mainViewModelProvider;

  private DaggerTestAppComponent(DispatchersModule dispatchersModuleParam, Context contextParam) {

    initialize(dispatchersModuleParam, contextParam);
  }

  public static TestAppComponent.Factory factory() {
    return new Factory();
  }

  private MyAdapter myAdapter() {
    return new MyAdapter(mainViewModelProvider.get());
  }

  @SuppressWarnings("unchecked")
  private void initialize(final DispatchersModule dispatchersModuleParam,
      final Context contextParam) {
    this.myRepositoryProvider = MyRepository_Factory.create((Provider) FakeSaveData_Factory.create());
    this.contextProvider = InstanceFactory.create(contextParam);
    this.provideDatabaseProvider = DoubleCheck.provider(RoomModule_Companion_ProvideDatabaseFactory.create(contextProvider));
    this.provideDaoProvider = DoubleCheck.provider(RoomModule_Companion_ProvideDaoFactory.create(provideDatabaseProvider));
    this.roomRepositoryProvider = RoomRepository_Factory.create(provideDaoProvider);
    this.providesIoDispatcherProvider = DispatchersModule_ProvidesIoDispatcherFactory.create(dispatchersModuleParam);
    this.mainViewModelProvider = DoubleCheck.provider(MainViewModel_Factory.create(myRepositoryProvider, roomRepositoryProvider, providesIoDispatcherProvider));
  }

  @Override
  public void inject(MainActivity arg0) {
    injectMainActivity(arg0);
  }

  @Override
  public void inject(ListFragment arg0) {
    injectListFragment(arg0);
  }

  private MainActivity injectMainActivity(MainActivity instance) {
    MainActivity_MembersInjector.injectViewModel(instance, mainViewModelProvider.get());
    return instance;
  }

  private ListFragment injectListFragment(ListFragment instance) {
    ListFragment_MembersInjector.injectRvAdapter(instance, myAdapter());
    return instance;
  }

  private static final class Factory implements TestAppComponent.Factory {
    @Override
    public TestAppComponent create(Context context) {
      Preconditions.checkNotNull(context);
      return new DaggerTestAppComponent(new DispatchersModule(), context);
    }
  }
}

If I don't have a room installed in the app Dagger will generate DaggerTestAppComponent.create(). It's once setup room Dagger stops generating DaggerTestAppComponent.create().

Dagger dependencies

    def dagger_version = "2.33"
    implementation "com.google.dagger:dagger:$dagger_version"
    kapt "com.google.dagger:dagger-compiler:$dagger_version"
    kapt "com.google.dagger:dagger-android-processor:$dagger_version"
    kaptAndroidTest "com.google.dagger:dagger-compiler:$dagger_version"

Build output

> Task :app:compileDebugAndroidTestKotlin FAILED
e: C:\Android\TestingEx\EndToEnd\app\src\androidTest\java\com\example\endtoend\TestApplication.kt: (14, 39): Unresolved reference: create


from Dagger not creating DaggerTestAppComponent.Test

No comments:

Post a Comment