4

I have the following multi project structure:

/
    build.gradle
    common/
        build.gradle
        src/main/
            resources/common.properties
            java/...
        src/test/
            resources/common.properties
            java/...
    app/
        build.gradle
        src/main/java/...
        src/test/java/...
    admin/
        build.gradle
        src/main/java/...
        src/test/java/...

common project contains some common methods and they have their own unit tests and one CommonDefs class which contains data loaded from common.properties. When running unit tests, the common.properties file from the test resources supposedly overrides the one in the main resources, and the tests do work as expected.

The problem begins when running unit tests for app and admin projects - which contain tests that use CommonDefs from the common project.

Up until now I've used a generic solution similar to the method described in the following SO answer and it has worked perfectly for a couple years. This is what the root build.gradle contains:

allprojects {
    plugins.withType(JavaPlugin) {
        configurations {
            testOutput
        }

        dependencies {
            testOutput sourceSets.test.output
        }
    }
}

and app/build.gradle & admin/build.gradle both contain:

dependencies {
    compile project(":common")
    testCompile project(path: ":common", configuration: "testOutput")
    // ...
}

I've decided it was time to upgrade Gradle (previously used 2.14.1), so I started testing the project against Gradle 4.2.1. Now every time I run the tests for app and admin, CommonDefs loads data from src/main/resources/common.properties instead of src/test/resources/common.properties.

I've tried printing the test classpath for the app project and it seems that Gradle 4.2.1 takes the common's main JAR first:

path\to\app\build\classes\java\test
path\to\app\build\resources\test
path\to\app\build\classes\java\main
path\to\app\build\resources\main
path\to\common\build\libs\common.jar
path\to\common\build\classes\java\test
path\to\common\build\resources\test

with Gradle 2.14.1 the result was:

path\to\app\build\classes\test
path\to\app\build\resources\test
path\to\app\build\classes\main
path\to\app\build\resources\main
path\to\common\build\classes\test
path\to\common\build\resources\test
path\to\common\build\libs\common.jar

Is there a way to tell the newer version of Gradle to prioritize the test output of common over its main output?

N.B

I also tried using the following in app/build.gradle:

evaluationDependsOn(":common")

dependencies {
    compile project(":common")
    testCompile project(":common").sourceSets.test.output
}

which seems to work, but it looks rather hacky and I'd like to stick to the solution with the configuration if possible.

Adi Gerber
  • 636
  • 7
  • 22
  • Relying on classpath ordering is always a bad idea, is there any chance you could move `common.properties` to `$env/common.properties`? You could then have unique paths eg `prod/common/properties`, `uat/common.properties`, `unit-test/common.properties` and `integ-test/common.properties` etc. You could use a system property to choose the $env (defaulted to "prod" for backwards compatability) – lance-java Jan 04 '18 at 11:56

0 Answers0