Dagger未为/test类生成组件。

77

我正在按照这里的指南进行操作:https://github.com/ecgreb/dagger-2-testing-demo

在我的app/src/main中,我有以下设置(省略了注入和@Provides代码):

public class FlingyApplication extends Application {
    @Singleton
    @Component(modules = { FlingyModule.class })
    public interface FlingyComponent
}

@Module
public class FlingyModule

在app/src/test目录下:

public class TestFlingyApplication extends Application {
    @Singleton
    @Component(modules = { TestFlingyModule.class })
    public interface TestFlingyComponent extends FlingyComponent
}

@Module
public class TestFlingyModule

目前,它几乎与github示例完全相同。当Dagger开始生成src/main中的Component构建器代码时,它们能够正确地生成。但是,Dagger并没有为src/test中的Component构建器生成代码。

我的主要build.gradle:

dependencies {
    classpath 'com.android.tools.build:gradle:2.1.0-alpha3'

    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.5.1'
}

我的app/build.gradle

apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'


android {
    # There is obviously more in here, but this is the custom part:
    packagingOptions {
        exclude 'META-INF/services/javax.annotation.processing.Processor'
    }
}

dependencies {
    compile 'com.squareup:otto:1.3.8'
    compile 'com.android.support:cardview-v7:23.1.1'
    compile 'com.android.support:recyclerview-v7:23.1.1'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'
    compile 'com.squareup.picasso:picasso:2.5.2'
    compile 'com.jakewharton:butterknife:7.0.1'

    compile 'com.google.dagger:dagger:2.0.1'
    apt 'com.google.dagger:dagger-compiler:2.0.1'
    compile 'javax.annotation:javax.annotation-api:1.2'

    compile 'io.reactivex:rxandroid:1.1.0'
    compile 'io.reactivex:rxjava:1.1.0'

    testCompile 'com.neenbedankt.gradle.plugins:android-apt:1.4'
    testCompile 'junit:junit:4.12'
    testCompile 'org.robolectric:robolectric:3.0'
    testCompile 'org.mockito:mockito-core:1.10.19'
}

因此,当我构建时,我会得到DaggerFlingyApplication_FlingyComponent类,但不会得到DaggerTestFlingyApplication_TestFlingyComponent

我注意到有趣的一点是,如果我交换这行代码:

apt 'com.google.dagger:dagger-compiler:2.0.1'
# TO
compile 'com.google.dagger:dagger-compiler:2.0.1'

当我运行./gradlew compileDebugUnitTestSources时,我看到以下内容:

:app:compileDebugJavaWithJavac
Note: /app/build/generated/source/apt/debug/com/jy/flingy/DaggerFlingyApplication_FlingyComponent.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
:app:preDebugUnitTestBuild UP-TO-DATE
:app:prepareDebugUnitTestDependencies
:app:compileDebugUnitTestJavaWithJavac
Note: /app/build/intermediates/classes/test/debug/com/jy/flingy/DaggerTestFlingyApplication_TestFlingyComponent.java uses unchecked or unsafe operations.

我不知道为什么它会构建到 intermediates,我猜想我需要使用 build.gradle 文件来使用 apt 而不是 compile,但我似乎无法搞清楚如何让它正常工作。我知道这是完全可能的。


这份文档(http://google.github.io/dagger/testing.html)建议不要在单元测试中使用dagger。 - Kishan B
如果你有很多依赖项,那么它可能指向你的单元测试测试不止一个单元。话虽如此,谷歌并不总是最好的选择(哇!),而且他们的说法相当宽泛。在特定情况下,在单元测试中使用dagger对我们来说效果很好,因此出现了这个问题。 - jyanks
https://dev59.com/mZnga4cB1Zd3GeqPW1Lr#60352086 - Anoop M Maddasseri
8个回答

144

你需要将以下内容添加到你的build.gradle文件中,以进行仪器测试:

androidTestApt 'com.google.dagger:dagger-compiler:<version>'

或者对于JUnit测试:

testApt 'com.google.dagger:dagger-compiler:<version>'

这是必须的,以生成用于测试组件的Dagger代码。


编辑:

如果您正在使用jack工具链,则需要添加以下内容以进行Android测试:

androidTestAnnotationProcessor 'com.google.dagger:dagger-compiler:<version>'

对于 JUnit 测试:

testAnnotationProcessor 'com.google.dagger:dagger-compiler:<version>'

编辑:

如果您正在使用 kotlin-kapt 处理 Kotlin 代码,请使用以下内容:

kaptAndroidTest 'com.google.dagger:dagger-compiler:<version>'

或者针对 JUnit 测试:

kaptTest 'com.google.dagger:dagger-compiler:<version>'

请查看此链接以获取更多信息。


4
我收到以下信息:错误:(55,0)Gradle DSL 方法未找到:'testApt()' - jyanks
5
我不得不将apt升级到1.7+... classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' 才能使testApt正常工作。 - jyanks
3
我尝试使用变量 "testAnnotationProcessor" 但是该类并没有被生成。请问您知道这种方法是否存在问题吗? - Leandro Ocampo
1
Jack 处理器的依赖关系与 /test 目录中的处理器不兼容。我切换到 apt 并且它工作得很好。因此,如果您需要这个功能,请放弃 Jack 并使用 apt。 - Jason Robinson
32
请记得执行测试或运行assembleAndroidTest以实际查看依赖类DaggerMyComponent的解析,仅使用rebuild不会生成来自dagger的类。 - jamesbluecrow
显示剩余9条评论

34

对于Android Studio 3和dagger2.13,需要使用已经提到的注解处理器:

testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.13'

同时也不要忘记对androidTest下的仪器化测试进行此操作:

androidTestAnnotationProcessor'com.google.dagger:dagger-compiler:2.13'

你可能会认为这样做不起作用,因为DaggerXYZ类没有被生成。经过几个小时的努力,我发现测试源代码生成只有在执行测试时才会触发。如果你从Android Studio开始一个testandroidTest,源代码生成应该会被触发。

如果您需要更早地触发此操作,请手动触发Gradle:

gradlew <moduledirectory>:compile<Flavor>DebugAndroidTestSources
gradlew <moduledirectory>:compile<Flavor>DebugTestSources

如果您在不同的构建类型中运行测试,请更换 Debug

注意:

如果您使用 multiDexEnable = true,则可能会出现错误:

测试运行失败:由于 'java.lang.IncompatibleClassChangeError' 而导致的仪器化运行失败

在这种情况下,请使用其他runner。

android {

  defaultConfig {
    multiDexEnabled true
    testInstrumentationRunner "com.android.test.runner.MultiDexTestRunner"

4
需要运行一些测试,然后Dagger将生成测试dagger类(组件)。+1 - Stoycho Andreev
我一直以为rebuild会覆盖整个项目, 但显然不是这样。谢谢。 - Viacheslav
androidTestAnnotationProcessor - 这就是我在寻找的,谢谢! - Johan Lund

29

仅为上面的回答增加一点内容,因为最近发生了一些变化。

从Android Gradle插件版本2.2及以上,您将不再使用testApt。

因此,从现在开始您只需在build.gradle中放置以下内容:

testAnnotationProcessor 'com.google.dagger:dagger-compiler:<version>'

但不仅如此,我来这里的目的还有以下几点:如果您需要 gradle 为您生成 DaggerComponent 类,则需要额外做一些工作。

打开我们的 build.gradle 文件,在 android 部分之后写入以下内容:

android.applicationVariants.all { variant ->
    if (variant.buildType.name == "debug") {
        def aptOutputDir = new File(buildDir, "generated/source/apt/${variant.unitTestVariant.dirName}")
        variant.unitTestVariant.addJavaSourceFoldersToModel(aptOutputDir)
        assembleDebug.finalizedBy('assembleDebugUnitTest')
    }
}

这将创建目录 build/generated/source/apt/test/ 作为 Java 类接收器,最后一部分将触发 "assembleDebugUnitTest" 任务,在刚刚创建的文件夹中创建这些 Dagger2 组件。

请注意,此脚本仅在“debug”变体中被触发,并利用该构建变体使用“assembleDebug”任务。如果由于某种原因您需要它在其他变体中,请稍微调整一下。

为什么 Dagger2 不自动执行这个操作超出了我的理解范围,但是嘿,我不是专家。


可以在我的电脑上运行,你可能错过了结尾的 } 符号。 - Efi MK
我喜欢这种方法,因为它不需要安装更多的Android库。因为我正在一个单独的库中进行TDD,所以我从android.libraryVariants.all开始。 - Juan Mendez
1
太棒了!在寻找 testApt 的替代方案上花费了数小时,这个方法解决了问题。谢谢! - saltandpepper
@saltandpepper,你在使用最新版本的Gradle时遇到了什么问题吗? - Shishir Shetty
谢谢。花了我两天时间才修好。Kotlin + Dagger 2.19 + 最新的gradle。 - Andrii Kovalchuk

18
如果您已经为Dagger依赖项添加了`kaptAndroidTest`,但重新构建项目时仍未获得测试组件,请尝试运行`assembleAndroidTest`。

1
我推荐这个答案,因为它可以帮助您查看依赖图或其他与依赖项无关的问题是否存在问题。 - Oscar Josue Alvrez
你救了我的一天,兄弟。我陷入这个问题很久了。 - Rizwan

3
在上述解决方案的基础上,为Dagger添加testKapt和androidTestKapt。我遇到了一个问题,由于缺少导入,我的模块和组件导入错误。例如:
 import android.support.test.espresso.core.deps.dagger.Module
 import android.support.test.espresso.core.deps.dagger.Module

代替
import dagger.Module
import dagger.Provides

希望这能有所帮助。

1
起初,我跳过了这个建议,因为我确信它不可能是问题所在,但在又花了20分钟进行调试后,我实际上去检查了导入。结果发现,令人惊讶的是,Android Studio出于某种原因自动导入了espresso版本。 - Nicholas
1
解决了问题,大脑太棒了。 - Mudassir Zulfiqar

2

你好,即使添加了所有的Gradle依赖项和注释,如果仍然无法正常工作,则需要运行assembleAndroidTest Gradle脚本。 只需创建一个空的测试用例并运行它即可。这将为您完成任务。 干杯


(注:Original Answer翻译成“最初的回答”)

天啊!我浪费了很多时间在“build”选项上。但实际上,即使是空测试,Dagger文件也会通过运行创建。 - Marjan Davodinejad

0

如果你正在使用 Kotlin,则在 build.gradle 文件中使用 "kaptAndroidTest" 生成 Dagger 组件以进行 Android 测试。


0

我在命令行中运行了./gradlew build,并得到了有关缺少提供方法的信息,而这是Android Studio没有告诉我的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接