5

According to 25.3.3. Excluding Test Configuration this capability exists:

When placed on a top-level class, @TestConfiguration indicates that classes in src/test/java should not be picked up by scanning

I created both @Configuration FilledWithBeanTestConfig and @TestConfiguration DummyTestConfig in the project's root path/package src/test/java/com/example/mvctries/. My main method-containing class is on purpose annotated with @ComponentScan just in order to accidentally pick FilledWithBeanTestConfig; about this situation Spring is specifically warning:

If your application uses component scanning (for example, if you use @SpringBootApplication or @ComponentScan), you may find top-level configuration classes that you created only for specific tests accidentally get picked up everywhere.

I used @Import(DummyTestConfig.class) in a @WebMvcTest annotated test class placed in src/test/java/com/example/mvctries/controller/; I was expecting for the @Configuration FilledWithBeanTestConfig to just be ignored but it wasn't. Moving DummyTestConfig to src/test/java/com/example/mvctries/controller/ also didn't help.

What am I doing wrong when testing the way presented above this src/test/java scanning-ignore capability?
How should I properly use @TestConfiguration in order to use this src/test/java scanning-ignore capability?
How would I test this capability by using @SpringBootApplication component scanning only instead of on purpose scanning with @ComponentScan?

While the above questions might seem too many they are in fact another way of asking the following one question: how would one craft a project which to clearly prove how @TestConfiguration usage leads to classes in src/test/java should not be picked up by scanning.

UPDATE

Here's the example project: https://github.com/adrhc/spring-boot-test-checks.git; it's using port 8083 when running the application; better run the test class.

Adrian
  • 3,321
  • 2
  • 29
  • 46
  • 1
    can you share a sample project? and explicitly mention what are you trying to achieve – Dhruv May 16 '19 at 01:48

2 Answers2

2

@ComponentScan without filter property will always load all @Configuration classes. @TestConfiguration works only for that one annotated class and not for the whole package/directory.

It seems like an unfortunate formulation in the docs - it discusses usage of @TestConfiguration on top level classes inside src/test/java rather than on the inner class of you test.

In short: Never use @ComponentScan without TypeExcludeFilter - it will start loading everything for all your SpringBootTest tests and also for tests using slices - which beats the purpose of having slices in the first place.

Once you get rid of @ComponentScan (or once you add the mentioned filter):

  • @SpringBootTest will load all @Configuration classes but will not load @TestConfiguration classes. @TestConfiguration classes can be picked when needed using @Import.
  • Test slices like @WebMvcTest will not load any extra custom classes / configurations unless you instruct them with @Import. If all your tests with @WebMvcTest (or other slice) need additional configuration then you can easily create your own slice or alter the existing one using META-INF/spring.factories file (a separate topic though).
Josef Cech
  • 2,115
  • 16
  • 17
0

When @ComponentScan is applied, then excludeFilters need to be added in order to avoid picking up @TestConfigurations by accident:

@ComponentScan(value = { "my.base.package" }, excludeFilters = {
        @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public class BootTestConfig { }

For reference: Look at @SpringBootApplication; it defines excludeFilters on @ComponentScan.

Markus Pscheidt
  • 6,853
  • 5
  • 55
  • 76