Search code examples
androiddagger-2dagger

dagger test component not being generated when the project contains multiple android modules


Android Studio 3.4
kotlin 1.3.0
dagger 2.21

I have a project that has a presentation and data module. And I am trying to create the test component in the data module. I can generate the component for the presentation module. I am using kotlin-kts for the gradle build.

For the presentation moudle I have the following build.gradle.kts

plugins {
    id("com.android.application")
    kotlin("android")
    kotlin("kapt")
}

android {
    compileSdkVersion(Versions.compileSdkVersion)

    defaultConfig {
        applicationId = "nz.org.westforce.mobileui"
        minSdkVersion(Versions.minSdkVersion)
        targetSdkVersion(Versions.targetSdkVersion)
        versionCode = Versions.versionCode
        versionName = Versions.versionName

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
        }
    }
}

dependencies {
    implementation(Libraries.appCompat)
    implementation(Libraries.kotlinStdlib)
    implementation(Libraries.daggerAndroid)
    implementation(Libraries.daggerSupport)
    kapt(Libraries.daggerCompiler)
    kapt(Libraries.daggerProcessor)

    androidTestImplementation(TestLibraries.runner)
    androidTestImplementation(TestLibraries.espressoCore)

    testImplementation(TestLibraries.junit)
    testImplementation(Libraries.daggerAndroid)
    testImplementation(Libraries.daggerSupport)

    kaptTest(Libraries.daggerCompiler)
    kaptTest(Libraries.daggerProcessor)

    implementation(project(":data"))
}

For the presentation module I have the following Application:

class WestforceCreditUnionMobileuiApplication
    : Application(), HasActivityInjector {

    @Inject
    lateinit var dispatchingAndroidActivityInjector: DispatchingAndroidInjector<Activity>

    override fun onCreate() {
        super.onCreate()

        DaggerWestforceCreditUnionMobileuiComponent.builder()
            .application(this)
            .build()
            .inject(this)
    }

    override fun activityInjector(): AndroidInjector<Activity> =
        dispatchingAndroidActivityInjector
}

The Component

@Singleton
@Component(modules = [AndroidSupportInjectionModule::class])
interface WestforceCreditUnionMobileuiComponent {
    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(application: WestforceCreditUnionMobileuiApplication): Builder

        fun build(): WestforceCreditUnionMobileuiComponent
    }

    fun inject(application: WestforceCreditUnionMobileuiApplication)
}

The above is working and the DaggerWestforceCreditUnionMobileuiComponent is generated

Now in my data module I can trying to create a test component but dagger doesn't generate the test component classes.

I have the following test component in java/test/package/di directory

@Singleton
@Component(modules = [TestNetworkModule::class])
interface TestWestforceCeditUnionComponent {
    fun inject(webServicesImpTest: WebServicesImpTest)
}

And in my test class:

class WebServicesImpTest {

    @Inject
    private lateinit var webServicesImp: WebServicesImp

    @Test
    fun setUp() {
        /* the DaggerTestWestforceCreditUnionComponent is not generated */
    }
}

I haven't specified the modules here as it will inflate the code here too much.

For my build.gradle.kts in the data module:

import org.gradle.kotlin.dsl.implementation

plugins {
    id("com.android.library")
    id("kotlin-android")
}

android {
    compileSdkVersion(Versions.compileSdkVersion)

    defaultConfig {
        minSdkVersion(Versions.minSdkVersion)
        targetSdkVersion(Versions.targetSdkVersion)
        versionCode = Versions.versionCode
        versionName = Versions.versionName

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
        }
    }
}

dependencies {
    implementation(Libraries.kotlinStdlib)
    implementation(Libraries.appCompat)
    implementation(Libraries.daggerAndroid)
    implementation(Libraries.daggerSupport)
    kapt(Libraries.daggerCompiler)
    kapt(Libraries.daggerProcessor)

    testImplementation(TestLibraries.junit)
    testImplementation(TestLibraries.assertJ)
    testImplementation(TestLibraries.mockitoKotlin)

    testImplementation(Libraries.daggerAndroid)
    testImplementation(Libraries.daggerSupport)
    kaptTest(Libraries.daggerCompiler)
    kaptTest(Libraries.daggerProcessor)
}

I am using the following dagger.android dependencies:

  const val daggerAndroid = "com.google.dagger:dagger-android:${Versions.daggerAndroidVersion}"
  const val daggerCompiler = "com.google.dagger:dagger-compiler:${Versions.daggerAndroidVersion}"
  const val daggerProcessor = "com.google.dagger:dagger-android-processor:${Versions.daggerAndroidVersion}"
  const val daggerSupport = "com.google.dagger:dagger-android-support:${Versions.daggerAndroidVersion}"

I have tried rebuilding the project and trying running the following task compileDebugUnitTestSources

Everything builds successfully,

One think I am thinking about as I am using different android modules, maybe the data module cannot see the WestforceCreditUnionMobileuiApplication in the presentation module.

Many thanks for any suggestions


Solution

  • You forgot to add

    kotlin("kapt")
    

    to plugins section in :data module build.gradle.kts.

    Gradle then proceeds with errors about missing @Provides for your WebServicesImp. Also you should fix the missing Context provider, in my example I just removed the Context use. This should be added to TestNetworkModule:

    @Singleton
    @Provides
    fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .baseUrl("http://www.holidaywebservice.com")
            .client(okHttpClient)
            .addConverterFactory(SimpleXmlConverterFactory.createNonStrict(Persister(AnnotationStrategy())))
            .build()
    }
    @Reusable
    @Provides
    fun provideWebServices(retrofit: Retrofit): WebServices {
        return retrofit.create(WebServices::class.java)
    }
    
    @Reusable
    @Provides
    fun provideWebServicesImp(webServices : WebServices): WebServicesImp {
        return WebServicesImp(webServices)
    }
    

    After that DaggerTestWestforceCeditUnionComponent was successfully generated.