Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Provide module-scoped equivalents to @WebMvcTest and @DataJpaTest #5

Open
thombergs opened this issue Jun 30, 2018 · 25 comments
Open

Comments

@thombergs
Copy link
Collaborator

thombergs commented Jun 30, 2018

With @WebMvcTest and @DataJpaTest we can easily create an ApplicationContext for the web- or data layer of our Spring Boot Application.

It would be nice to have equivalents to these annotations that only include the web- or data layer of our module under test into the ApplicationContext.

Same goes for the other annotations like @WebfluxTest, @JdbcTest and so on (see https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html).

@thombergs thombergs changed the title Provide equivalents to @WebMvcTest and @DataJpaTest Provide equivalents to @WebMvcTest and @DataJpaTest Jun 30, 2018
@thombergs thombergs changed the title Provide equivalents to @WebMvcTest and @DataJpaTest Provide module-scoped equivalents to @WebMvcTest and @DataJpaTest Jun 30, 2018
@odrotbohm
Copy link
Collaborator

Ideally, I'd love to see the annotations to work properly in combination rather than having to replicate all of them into this project. I guess that's currently not working properly as Boot is not expecting multiple of these annotations to be used at the same time.

I'll take this request forward to the Boot team to see what we can do here.

@thombergs
Copy link
Collaborator Author

With "in combination", you mean "in combination with @ModuleTest (or any other scope-constraining annotation, for that matter)", so that it would look something like this, right?

@RunWith(SpringRunner.class)
@DataJpaTest
@ModuleTest
public class MyModuleDataLayerTests {
  // ...
}

@odrotbohm
Copy link
Collaborator

Exactly. Did you try that already?

@thombergs
Copy link
Collaborator Author

Did so just now:

@RunWith(SpringRunner.class)
@WebMvcTest
@ModuleTest
public class BookingControllerTest {
  ...
}

leads to

java.lang.IllegalStateException: Configuration error: found multiple declarations of 
@BootstrapWith for test class [com.acme.myproject.booking.web.BookingControllerTest]: 
[@org.springframework.test.context.BootstrapWith(value=class 
org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTestContextBootstrapper), 
@org.springframework.test.context.BootstrapWith(value=class 
org.springframework.boot.test.context.SpringBootTestContextBootstrapper)]

@odrotbohm
Copy link
Collaborator

odrotbohm commented Jul 2, 2018

Interesting. Does it also fail in this way if you use e.g. @DataJpaTest which also declares SpringBootTestContextBootstrapper? Nevermind, I just checked Spring Test Context Framework's code and it will.

@wilkinsona – it looks like Spring's BootstrapUtils.resolveExplicitTestContextBootstrapper(…) is rather strict as it already fails if two @BootstrapWith annotations are found without ever considering them to potentially point to the same (or at least compatible) bootstrappers. I guess it's something we need @sbrannen's help for.

@sbrannen
Copy link
Collaborator

sbrannen commented Jul 4, 2018

I've created the following JIRA issue to address this (at least partially).

https://jira.spring.io/browse/SPR-17006

Feedback on the JIRA issue is welcome.

@sbrannen
Copy link
Collaborator

sbrannen commented Jul 4, 2018

it looks like Spring's BootstrapUtils.resolveExplicitTestContextBootstrapper(…) is rather strict as it already fails if two @BootstrapWith annotations are found without ever considering them to potentially point to the same (or at least compatible) bootstrappers.

I actually just introduced a test for "the same" use case, and that already works since resolveExplicitTestContextBootstrapper() uses a Set.

For example, the bootstrapper resolved for DuplicateMetaAnnotatedBootstrapWithAnnotationClass is FooBootstrapper.

	@BootstrapWith(FooBootstrapper.class)
	@Retention(RetentionPolicy.RUNTIME)
	@interface BootWithFoo {}

	@BootstrapWith(FooBootstrapper.class)
	@Retention(RetentionPolicy.RUNTIME)
	@interface BootWithFooAgain {}

	@BootWithFoo
	@BootWithFooAgain
	static class DuplicateMetaAnnotatedBootstrapWithAnnotationClass {}

Thus, it would appear that only the "compatible" use case is not supported.

Can you confirm that?

@sbrannen
Copy link
Collaborator

sbrannen commented Jul 4, 2018

For the new test, see: spring-projects/spring-framework@755add3

@odrotbohm
Copy link
Collaborator

odrotbohm commented Jul 4, 2018

According to Sam, @DataJpaTest and @ModuleTest should then already work together. Would you mind trying that, Tom?

@thombergs
Copy link
Collaborator Author

Yes, @DataJpaTest works in combination with @ModuleTest. I actually had already tried that already and found that all repositories are loaded and not just the ones from the module (see issue #4).

@sbrannen
Copy link
Collaborator

sbrannen commented Jul 5, 2018

OK. Thanks for the confirmation.

@sbrannen
Copy link
Collaborator

sbrannen commented Jul 5, 2018

@olivergierke, do you think you still need new support for the "compatible" use case in the TCF?

@odrotbohm
Copy link
Collaborator

@sbrannen – Ultimately, yes. I'd love to get the input of the Boot team (@wilkinsona, @philwebb) on whether using these annotations in combination is something they're intending to work towards. I totally understand that the annotations that Boot currently ships don't really create that scenario.

@thombergs – Re #4, did you see my comment there?

@odrotbohm
Copy link
Collaborator

@sbrannen – I've just tried a naive attempt for disambiguation by explicitly declaring an @BootstrapWith(…) locally hoping that local declaration would override the meta-ones defined in the other annotations:

@RunWith(SpringRunner.class)
@DataJpaTest
@WebMvcTest
@BootstrapWith(WebMvcTestContextBootstrapper.class)
public class SomeTest { … }

Is making that work maybe a cheap intermediate solution?

@sbrannen
Copy link
Collaborator

sbrannen commented Jul 5, 2018

Ultimately, yes. I'd love to get the input of the Boot team (@wilkinsona, @philwebb) on whether using these annotations in combination is something they're intending to work towards. I totally understand that the annotations that Boot currently ships don't really create that scenario.

OK. Then I'll hold off until the Boot team provides feedback in this regard.

@sbrannen
Copy link
Collaborator

sbrannen commented Jul 5, 2018

Is making that work maybe a cheap intermediate solution?

By "that" do you mean favoring a locally declared annotation over a meta-annotation on a locally declared composed annotation?

@sbrannen
Copy link
Collaborator

sbrannen commented Jul 5, 2018

Oh wait.... embarrassing... just read your lead-in comment. 😇

@sbrannen
Copy link
Collaborator

sbrannen commented Jul 5, 2018

In any case, to answer your question....

See https://jira.spring.io/browse/SPR-12602.

That was an issue raised by @philwebb to ensure that multiple competing declarations of @BootstrapWith are not allowed.

@sbrannen
Copy link
Collaborator

sbrannen commented Jul 5, 2018

Is making that work maybe a cheap intermediate solution?

In light of SPR-12602, that would be a breaking change.

So I'm not so sure we should do that.......

@odrotbohm
Copy link
Collaborator

I’d argue it wouldn’t. The same code would still fail with the same error message. It would only allow the developer to resolve the ambiguity by adding an explicit override.

@sbrannen
Copy link
Collaborator

sbrannen commented Jul 6, 2018

mmmm... The meta-presence of more than one such annotation would continue to be an error. So in that sense, I suppose you're correct.

Plus, if anyone had previously tried what you tried above, that would have failed then, and they would have stopped doing it.

So, yeah, it wouldn't actually be a breaking change to any "working" code. Rather, it would be a change in behavior that someone would have to opt in for.

In other words, I agree. 😉

@sbrannen
Copy link
Collaborator

sbrannen commented Jul 6, 2018

@odrotbohm
Copy link
Collaborator

Looks like @sbrannen was kind enough to add support for an escape hatch by adding an explicit annotation on the test class in Spring Framework 5.1.

Would you mind giving this another look on 5.1, @thombergs?

@tilm4nn
Copy link

tilm4nn commented May 18, 2022

I just tried to verify this with @BootstrapWith(WebMvcTestContextBootstrapper.class) on the test class.
Unfortunately this does not work with our SpringFramework in use (version 5.3.19) because class WebMvcTestContextBootstrapper is access level friendly and not public. So no access from Test.

In addition I tried to use @AutoConfigureMockMvc on the test class instead of @WebMvcTest.
This works well when used together with @SpringBootTest but unfortunately not with @ModuleTest.

@tilm4nn
Copy link

tilm4nn commented May 18, 2022

I just realized that the test works when I specify all three together

@ModuleTest
@SpringBootTest
@AutoConfigureMockMvc

But what does this mean for the bootsrapping? Does it initialize the whole application or only the current module?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants