hamvocke/spring-testing

why PersonRepositoryIntegrationTest doesn't fail with h2 dependency with runtimeOnly gradle scope?

Azatick94 opened this issue · 4 comments

hi. Thanks for the interesting article about testing.

I was reading the following text from your article "I've defined H2 as a test dependency in the build.gradle file. The application.properties in the test directory doesn't define any spring.datasource properties. This tells Spring Data to use an in-memory database. As it finds H2 on the classpath it simply uses H2 when running our tests."

And I see the following:

  1. in article h2 is presented as test dependency but actually on code I see in build.gradle runtimeOnly scope.
  2. can you please explain why runtimeOnly 'com.h2database:h2' still works when I run PersonRepositoryIntegrationTest ? I thought that h2 is in runtime classpath and the test should fail due to dependencies. But it doesn't.

I see where your confusion is coming from. This was just me being sloppy with my words. When I write "I defined H2 as a test dependency" I didn't mean to be as precise as to suggest that I declared it as testRuntimeOnly. I declare h2 via runtimeOnly which makes it available for the application runtime and the test runtime alike.

You should be able to change the build.gradle declaration to testRuntimeOnly if you really want to enforce that H2 is never used outside of a test context. I didn't have such a strong opinion when I wrote this article, that's why I simply went with the more relaxed runtimeOnly declaration.

@hamvocke . Thanks for response.
I checked the definition of runtimeOnly from here (https://kb.novaordis.com/index.php/Gradle_Java_Plugin#The_.22main.22_Source_Set) and it's written that runtimeOnly configuration defines dependencies that are necessary to run the main source set code, but not for compilation. And main source doesn't include tests folder. This was my concern.

But I think I figured it out. I noticed that com.h2database:h2 dependency is included as a transitive dependency of org.springframework.boot:spring-boot-starter-test, and it is marked with (*) as a runtimeOnly dependency. So because of this I think there is no difference between scopes runtimeOnly and testRuntimeOnly in case of h2 dependency.

The transitive dependency from spring-boot-starter-test might be part of the solution, I agree.

I think your explanation for runtimeOnly and testRuntimeOnly isn't quite right. Gradle's documentation for the java plugin states that testRuntimeOnly extends runtimeOnly. In other words: all dependencies declared via runtimeOnly will also be available for the test source set's runtime. The Gradle doc is a little clumsy when it comes to describing the behavior, the link you provided is a little clearer here:

The Java plugin "testRuntimeOnly" configuration defines dependencies that are necessary to run the test source set code, but not for compilation. Extends runtimeOnly, everything available on runtimeOnly will also be available on "testRuntimeOnly". This configuration is used by the test Java plugin task.

oh. thanks. now everything is clear.