dagger2 和 kotlin 的 Android 单元测试问题

Posted

技术标签:

【中文标题】dagger2 和 kotlin 的 Android 单元测试问题【英文标题】:Android unit testing issues with dagger2 and kotlin 【发布时间】:2020-07-14 01:15:41 【问题描述】:

我正在尝试在 android 的 test 文件夹中创建一个 dagger 组件接口,但是在 Dagger 完成生成的类后,它显示错误为“无法访问 TestComponent,它是 com.example.animals.di 的超类型。 DaggerTestAppComponent.Check your module classpath for missing or conflicting dependency"。你能帮我解决这个问题吗?

gradle dependecies:
def lifeCycleExtensionVersion = '1.1.1'
def supportVersion = '28.0.0'
def retrofitVersion = '2.3.0'
def glideVersion = '4.9.0'
def rxJavaVersion = '2.1.1'
def navVersion = '2.1.0-alpha05'
def daggerVersion = '2.14.1'
def mockitoVersion = '2.11.0'

dependencies 
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.core:core-ktx:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation "com.android.support:design:$supportVersion"
    implementation "android.arch.lifecycle:extensions:$lifeCycleExtensionVersion"

    implementation "androidx.navigation:navigation-fragment-ktx:$navVersion"
    implementation "androidx.navigation:navigation-ui-ktx:$navVersion"

    implementation "com.squareup.retrofit2:retrofit:$retrofitVersion"
    implementation "com.squareup.retrofit2:converter-gson:$retrofitVersion"
    implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofitVersion"

    implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion"
    implementation "io.reactivex.rxjava2:rxandroid:$rxJavaVersion"

    implementation "com.github.bumptech.glide:glide:$glideVersion"

    implementation "com.android.support:palette-v7:$supportVersion"


    implementation "com.google.dagger:dagger:$daggerVersion"
    implementation "com.google.dagger:dagger-android-support:$daggerVersion"
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    kapt "com.google.dagger:dagger-compiler:$daggerVersion"
    kapt "com.google.dagger:dagger-android-processor:$daggerVersion"


    testImplementation "org.mockito:mockito-inline:$mockitoVersion"
    testImplementation "android.arch.core:core-testing:1.1.1"
    kaptTest "com.google.dagger:dagger-compiler:$daggerVersion"

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.2.0'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
 

TestAppComponent:
   package com.example.animals.di

 import com.example.animals.base.BaseTest
 import dagger.Component
 import javax.inject.Singleton

@Singleton
@Component(modules = [])
interface TestAppComponent 
   fun inject(baseTest: BaseTest)

基础测试: 包 com.example.animals.base

 import android.app.Application
 import com.example.animals.di.DaggerTestAppComponent
 import org.junit.Before
 import org.mockito.Mockito

open class BaseTest 

    val application = Mockito.mock(Application::class.java)

    @Before
     fun setUp() 
     configureDi()

    

    private fun configureDi() 
       var testAppComponent = DaggerTestAppComponent.builder().build()

        testAppComponent.inject(this)
    
 

【问题讨论】:

我有同样的问题,但有趣的是它仍然可以编译并且即使它抱怨它仍然可以工作????‍♂️ 是的,完全正确。无论如何,我现在找到了一种使用 daggerappcomponent 类的不同方法。我没有在测试中创建一个全新的方法,而是开始使用在开发过程中已经创建的那个,它运行良好现在很好,我觉得后者是使用匕首类的更好方法。 【参考方案1】:

我在 our repo here 上设置测试时遇到了同样的问题。 在查看来自 Tivi 的示例时,我注意到我们生成的源没有包含在源集中。

在项目的某处添加 gradle 脚本应该可以解决您的问题。

例如:https://github.com/toggl/android/blob/768f01b55c47ffd3bb7c4a82dea4abf50eac9e1c/database-android/build.gradle#L46-L63(与 Tivi 相同)。

main.java.srcDirs += 'src/main/kotlin'
debug.java.srcDirs += 'src/debug/kotlin'
release.java.srcDirs += 'src/release/kotlin'
test.java.srcDirs += 'src/test/kotlin'

// For kapt stubs
main.java.srcDirs += [file("$buildDir/generated/source/kapt/main")]
debug.java.srcDirs += [file("$buildDir/generated/source/kapt/debug")]
release.java.srcDirs += [file("$buildDir/generated/source/kapt/release")]
test.java.srcDirs += [file("$buildDir/generated/source/kapt/test")]

// For kotlin code gen during kapt
main.java.srcDirs += [file("$buildDir/generated/source/kaptKotlin/main")]
debug.java.srcDirs += [file("$buildDir/generated/source/kaptKotlin/debug")]
release.java.srcDirs += [file("$buildDir/generated/source/kaptKotlin/release")]
test.java.srcDirs += [file("$buildDir/generated/source/kaptKotlin/test")]

【讨论】:

非常感谢大卫。

以上是关于dagger2 和 kotlin 的 Android 单元测试问题的主要内容,如果未能解决你的问题,请参考以下文章

Dagger2 + Kotlin:lateinit 属性尚未初始化

没有Dagger2的Android Kotlin MVVM结构

kotlin + Dagger2 :没有@Provides-annotated 方法就无法提供

Kotlin + Dagger2:不能在没有 @Inject 构造函数或 @Provides- 或 @Produces-annotated 方法的情况下提供

Android kotlin 使用Dagger2报错 InvocationTargetException 不能生成DaggerXXComponent

Kotlin + Dagger2 出现 Dagger does not support injection into private fields 解决方案