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 to implement the Dagger into the tests.
Here's a link to the repository on Github. https://github.com/Shawn-Nichol/EndToEnd
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
, Graph for AndroidTest scope set.
@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
source set.
dependencies {
...
kaptAndroidTest "com.google.dagger:dagger-compiler:$dagger_version"
}
step 5 update application
MyApplication
open class MyApplication : Application() {
val appComponent: AppComponent by lazy {
initializeComponent()
}
open fun initializeComponent(): AppComponent {
return DaggerAppComponent.factory().create(applicationContext)
}
}
Step 6
TestApplication
class TestApplication : MyApplication() {
override fun initializeComponent(): AppComponent {
return DaggerTestAppComponent.create()
}
}
After completing these steps, I run a test so Dagger can generate the DaggerTestAppComponent
but it doesn't generate a DaggerTestAppComponent.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