Manage transitive dependencies with TestKit

I have a Plugin which reacts on given Plugins.
My Plugin has a dependency which brings guava:18 as transitive dependency into the game.

dependencies {
  implementation("some:dep:1.0") // <- Has guava:18 as dependency
}

But when my Plugin is used inside an Android Project, then the AGP brings guava:22 into the game.
The thing is: When both Plugins (my and the AGP) are applied in a “real” project; both guava dependencies are in the same classpath and Gradle picks correctly guava:22.
This works fine.
Unfortunately in TestKit tests where I declare the AGP as a “optionalPlugin” like this:

val optionalPlugins by configurations.creating {
  configurations["compileOnly"].extendsFrom(this)
}

dependencies {
  optionalPlugins("com.android.tools.build:gradle:3.1.4")
}

tasks.withType<PluginUnderTestMetadata> {
  pluginClasspath.from(optionalPlugins)
}

guava:18 is still used and the AGP crash. Because it uses an API of guava:21+.

How can I fix it? So that guava:22 is used in my tests?

One solution would be:
Exclude guava from my Plugin dependency and declare directly guava:22.

dependencies {
  implementation("some:dep:1.0") // <- Has guava:18 as dependency {
    exclude(module = "guava")
  }
  implementation("google:guava:22")
}

This works. but the downsite is that my Plugin will always use guava:22. But my dependencies only needs guava:18 when my Plugin is not used inside an AGP Project. So there is no need to “manually” upgrade it for the “real world”. But when the AGP is applied then guava:22 will be used anyway.

What I like to have:
Add guava:22 to my tests only. So that my Plugin dependency (which brings guava:18) will pick guava:22.
But I don’t know how to do this.
Any ideas?

(I use the TestKit with withPluginClasspath())

I found another solution which nearly fits my needs:

tasks.withType<PluginUnderTestMetadata> {
    pluginClasspath.from(optionalPlugins)
    val classpathWithoutGuava18 = pluginClasspath.files.filter { !it.path.contains("guava-18.0") }
    pluginClasspath.setFrom(classpathWithoutGuava18)
}

This will remove guava:18 from the TestKit test classpath.
Means that only guava:22 is left in our test.

Unfortunately my Plugin test test Plugin without AGP uses guava:22 too but I think I can live with that…

1 Like