Testing 对于具有compileOnly依赖项的单元测试,如何避免在运行时重新声明依赖项以获得可用性?

Testing 对于具有compileOnly依赖项的单元测试,如何避免在运行时重新声明依赖项以获得可用性?,testing,gradle,dependencies,Testing,Gradle,Dependencies,我目前正在使用Gradle构建一个项目,它依赖于 我在编译时需要的第三方组件,但将在运行时提供。 在maven中,我将按照提供的方式声明此依赖项,在Gradle中,我将其声明如下: compileOnly group: 'org.apache.spark', name: 'spark-sql_2.11', version: '2.4.0.cloudera1' 事实上,我依赖于上面的spark工件与这个问题并不密切相关(我提供这些信息是为了使示例更具体。) 现在,假设我想为我的应用程序(或库

我目前正在使用Gradle构建一个项目,它依赖于 我在编译时需要的第三方组件,但将在运行时提供。 在maven中,我将按照提供的方式声明此依赖项,在Gradle中,我将其声明如下:

  compileOnly group: 'org.apache.spark', name: 'spark-sql_2.11', version: '2.4.0.cloudera1'
事实上,我依赖于上面的spark工件与这个问题并不密切相关(我提供这些信息是为了使示例更具体。)

现在,假设我想为我的应用程序(或库,视情况而定)编写一些单元测试。 当使用Gradle时,我唯一知道如何做到这一点的方法就是笨重:我重新声明 依赖项作为testCompile依赖项,并且我的测试能够运行:

  compileOnly group: 'org.apache.spark', name: 'spark-sql_2.11', version: '2.4.0.cloudera1'
  testCompile group: 'org.apache.spark', name: 'spark-sql_2.11', version: '2.4.0.cloudera1'
我真的不喜欢重复和混乱的声明我的依赖两次,我想知道 在Gradle有没有更好的方法

结论

迈克的回答让我想到了我选择的解决方案,那就是把它放在我的多项目构建的顶级gradle文件中

subprojects {

  sourceSets {
    test.compileClasspath += configurations.compileOnly
    test.runtimeClasspath += configurations.compileOnly
  }
}

这实际上是一种非常标准的方式来声明渐变依赖项。在许多情况下,可以使用
compileOnly
依赖项,但并非所有这些都要求在运行时提供依赖项(不同于Maven的
provided
scope)

Gradle最初发布的仅编译依赖项()中对此作了进一步的详细说明:

仅编译依赖关系解决了许多用例,包括:

  • 在编译时需要依赖项,但在运行时从不需要依赖项,例如仅源代码注释或注释处理器
  • 编译时需要依赖项,但只有在使用某些功能时才需要依赖项,也称为可选依赖项
  • 其API在编译时是必需的,但其实现将由消费库、应用程序或运行时环境提供的依赖项
您所拥有的是一种惯用的方法,即为您的主要源声明一个仅编译的依赖项,这也是您的测试源的一个运行时依赖项(尽管从技术上讲,最新的Gradle版本建议您将不推荐使用的
testCompile
配置替换为
testImplementation
配置)

然而,Gradle的一个优点是它具有高度的可定制性。可以修改内置配置,例如
compileOnly
testImplementation
。如果希望更改内置行为,可以修改
testImplementation
配置以扩展
compileOnly
配置,这将导致在解决
testImplementation
时包含所有
compileOnly
依赖项:

// give test dependencies access to compileOnly dependencies to emulate providedCompile
configurations {
    testImplementation.extendsFrom compileOnly
}

来源:

这实际上是一种非常标准的声明渐变依赖项的方法。在许多情况下,可以使用
compileOnly
依赖项,但并非所有这些都要求在运行时提供依赖项(不同于Maven的
provided
scope)

Gradle最初发布的仅编译依赖项()中对此作了进一步的详细说明:

仅编译依赖关系解决了许多用例,包括:

  • 在编译时需要依赖项,但在运行时从不需要依赖项,例如仅源代码注释或注释处理器
  • 编译时需要依赖项,但只有在使用某些功能时才需要依赖项,也称为可选依赖项
  • 其API在编译时是必需的,但其实现将由消费库、应用程序或运行时环境提供的依赖项
您所拥有的是一种惯用的方法,即为您的主要源声明一个仅编译的依赖项,这也是您的测试源的一个运行时依赖项(尽管从技术上讲,最新的Gradle版本建议您将不推荐使用的
testCompile
配置替换为
testImplementation
配置)

然而,Gradle的一个优点是它具有高度的可定制性。可以修改内置配置,例如
compileOnly
testImplementation
。如果希望更改内置行为,可以修改
testImplementation
配置以扩展
compileOnly
配置,这将导致在解决
testImplementation
时包含所有
compileOnly
依赖项:

// give test dependencies access to compileOnly dependencies to emulate providedCompile
configurations {
    testImplementation.extendsFrom compileOnly
}

资料来源:

请注意,Mike提供的答案更为惯用,并且正确处理了可解析配置和不可解析配置之间的差异
compileOnly
resolution(将由您的方法触发)应发出不推荐警告,并在即将发布的Gradle版本中变得非法。请注意,Mike提供的答案更为惯用,并正确处理可解析配置和不可解析配置之间的差异
compileOnly
resolution将由您的方法触发,它将发出弃用警告,并在即将发布的Gradle版本中变得非法。