I have a highly-modularized project and I would like to declare one more separate module for some special test suite. Also, I don't want to repeat declaration of any dependencies which are already in classpath of the main application's module, so I would like to extend one Gradle configuration (in other words "dependencies scope") from another (the same way any implementation
dependency from src/main
becomes visible to src/test
in default case).
If I had a single module, I would just declare one more test suite with testing {}
DSL and extend one configuration from another to inherit dependencies from src/main
to src/myCustomTestSuite
.
And the following works as expected within the single module:
plugins {
`java-library`
}
repositories {
mavenCentral()
}
dependencies {
implementation("commons-codec:commons-codec:1.15")
}
testing {
suites {
val acceptanceTest by registering(JvmTestSuite::class) {
description = "Runs acceptance tests."
useJUnitJupiter()
}
}
}
val acceptanceTestImplementation by configurations.getting {
extendsFrom(configurations.implementation.get()) // <-- ✅ 'commons-code' becomes available for my tests in `src/acceptanceTest`
}
The problem appears when I try to extend configuration located in another module. Suppose I have a Gradle project with 2 modules: foo
and bar
.
├── bar
│ ├── build.gradle.kts
│ └── src
│ └── acceptanceTest
│ └── java
│ └── example
│ └── ExampleTest.java
├── build.gradle.kts
├── foo
│ └── build.gradle.kts
└── settings.gradle.kts
:foo
module declares 'commons-codec'implementation
-dependency forsrc/main
plugins {
`java-library`
}
repositories {
mavenCentral()
}
dependencies {
implementation("commons-codec:commons-codec:1.15")
}
- Now in
:bar
I would like to create a special test suite inheriting dependencies from:foo.implementation
:
plugins {
`java-library`
}
repositories {
mavenCentral()
}
testing {
suites {
val acceptanceTest by registering(JvmTestSuite::class) {
useJUnitJupiter()
}
}
}
val acceptanceTestImplementation by configurations.getting {
extendsFrom(project(":foo").configurations.implementation.get()) // <-- ❌ this one does not work as expected
}
Instead of an expected result, Gradle fails to initialize the project with an error at: bar/build.gradle.kts
, saying:
FAILURE: Build failed with an exception.
...
Configuration with name 'implementation' not found.
I also have additional observation: If I rename :bar
to :goo
(which means it will be after :foo
alphabetically), Gradle won't fail on initialization, but 'commons-code' won't be inherited to become visible for test code at :goo/src/accetpanceTest
. Compilation of src/acceptanceTest/java/example/ExampleTest.java
will fail with:
ExampleTest.java:3: error: package org.apache.commons.codec.binary does not exist
Looks like the problem appears because the configuration I want to inherit from gets evaluated lazily. How to fix that problem and achieve an expected result?