Declare dependencies of application so they are available transitively?


I have a decently sized Gradle project that I have recently upgraded to Gradle 4.10. As part of this, I’m trying to future-proof the application by using the new dependency scopes (implementation, runtimeOnly, etc.).

I have the main application working. However, I have an integration test module that is no longer properly loading the application because its dependencies are hidden. The structure looks roughly like this:

  |- build.gradle [master build file, sets up dependency management and common config]
  |- myproj-app/ [Spring Boot application]
  |   \- build.gradle [Uses 'java' plugin, declares implementation and runtimeOnly dependencies]
  |- myproj-lib-stuff/ [Shared application library]
  |   \- build.gradle [Uses 'java-library' plugin, declares implementation dependencies]
  |- myproj-integ-test/ [Integration tests to exercise the whole application]
  \   \- build.gradle [Uses 'java' plugin, declares myproj-app as an integTestImplementation dependency]

I realize that the Integ Test project can’t see the transitive dependencies of the application (and its dependencies), because that’s how the implementation configuration works. What I can’t figure out is which configuration to use that will do what I want, short of falling back to the deprecated compile config.

I’ve been fighting this for a few days now, so I thought I should ask for some guidance.

I should mention that I have a separate integration test module because of the way that this project works – the application doesn’t have a direct dependency on some of the libraries. The integ test module allowed me to structure those dependencies differently, so they could be tested all together, without polluting the classpath and artifact of the main application.

Perhaps with the way the new configurations are isolated, I no longer need to do this? I’m open to eliminating that separate module if that’s the case.

You could use api for that. But api is only available in the java-library plugin - which is not really recommended for “application” projects :upside_down_face:.
But when I understand you correctly your integ test module requires access to your app module (for testing different dependencies?!) somehow… So yeah - a fallback to compile would work - or using the java-library plugin instead of the java plugin.

I think about the whole setup.
I don’t know if its a good idea to use your application as a dependency for another module.
That sounds a little bit wrong to me.

Thanks for the reply, Stefan. I agree that it’s an unorthodox setup. This application is built with a plugin architecture, so that the application itself does not know at compile-time about the plugins. It’s very important to me that the plugins don’t leak into the application. I want a very strict separation there.

I guess it boils to down to reverting at least some of the dependencies to ‘compile’, or pulling the integration tests into the application and trusting Gradle’s dependency resolution to keep them separate (as a side note, IntelliJ does not seem to respect that separation – even if I introduce a ‘testRuntimeOnly’ dependence on a plugin library, it lets me use that library’s classes directly in the application). A third option is for the integ-test module to manually track all of the project’s direct dependencies, which seems like a maintenance nightmare.

For now, I’ve merged the integ test module into the main application. I’ll roll with that.