Boot version: 2.3.6.RELEASE
Let's say that we have the following production classes:
package a;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LoanOrdersApplication {
    public static void main(String[] args) {
        SpringApplication.run(LoanOrdersApplication.class, args);
    }
}
A controller
package a.controller;
import a.order.LoanOrder;
import a.order.LoanOrderService;
import reactor.core.publisher.Mono;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/orders")
public class LoanOrderController {
    private final LoanOrderService loanOrderService;
    public LoanOrderController(LoanOrderService loanOrderService) {
        this.loanOrderService = loanOrderService;
    }
    @GetMapping(path = "/{orderId}")
    Mono<LoanOrder> findOrder(@PathVariable String orderId) {
        return loanOrderService.findOrder(orderId);
    }
}
A service
package a.order;
public interface LoanOrderService {
    Mono<LoanOrder> findOrder(String orderId);
}
and the following test class:
package a;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class LoanOrdersApplicationTests {
    @Test
    void contextLoads() {
    }
}
According to the documentation (https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-testing-spring-boot-applications-detecting-config) what will happen now is that
When testing Spring Boot applications, this is often not required. Spring Boot's @*Test annotations search for your primary configuration automatically whenever you do not explicitly define one.
and according to the javadocs
If no explicit classes are defined the test will look for nested @Configuration classes, before falling back to a @SpringBootConfiguration search.
Great, I can see in the logs that the proper configuration was found cause I haven't passed the configuration explicitly.
15:13:35.700 [main] DEBUG org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider - Identified candidate component class: file [/home/foo/bar/target/classes/a/LoanOrdersApplication.class]
15:13:35.701 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Found @SpringBootConfiguration a.LoanOrdersApplication for test class a.LoanOrderControllerTest
Let's say that now I want to create a new test, where I want to test only the controller layer with mocked out services. I don't want to use test slices - I want to set up the Boot context without certain autoconfigurations (like Spring Data for example). I will create the controller by myself and also a mock of a service (I'm using @TestConfiguration so that the test that checks the whole context against the LoanOrderApplication doesn't pick my test configuration).
@SpringBootTest(classes = LoanOrderControllerTest.ControllerWithFakeConfig.class)
class LoanOrderControllerTest {
    @Test
    void contextLoads() {
    }
    @TestConfiguration(proxyBeanMethods = false)
    @EnableAutoConfiguration
    static class ControllerWithFakeConfig {
        @Bean
        LoanOrderService testLoanOrderService() {
            return Mockito.mock(LoanOrderService.class);
        }
        @Bean
        LoanOrderController testLoanOrderController(LoanOrderService loanOrderService) {
            return new LoanOrderController(loanOrderService);
        }
    }
}
Running LoanOrderControllerTest makes the build fail because there already is a LoanOrderController.
java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:123)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
    at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:43)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244)
    at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:98)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$5(ClassBasedTestDescriptor.java:341)
...
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webHandler' defined in class path resource [org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration$EnableWebFluxConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration$EnableWebFluxConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'testLoanOrderController' method 
pl.smarttesting.loanorders.controller.LoanOrderController#findOrder(String)
to {GET /orders/{orderId}}: There is already 'loanOrderController' bean method
pl.smarttesting.loanorders.controller.LoanOrderController#findOrder(String) mapped.
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:405)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
    at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    ... 66 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration$EnableWebFluxConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'testLoanOrderController' method 
pl.smarttesting.loanorders.controller.LoanOrderController#findOrder(String)
to {GET /orders/{orderId}}: There is already 'loanOrderController' bean method
pl.smarttesting.loanorders.controller.LoanOrderController#findOrder(String) mapped.
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1794)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:624)
    at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1251)
    at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:378)
    at org.springframework.web.reactive.DispatcherHandler.initStrategies(DispatcherHandler.java:116)
    at org.springframework.web.reactive.DispatcherHandler.setApplicationContext(DispatcherHandler.java:111)
    at org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:123)
    at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:100)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:415)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1786)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
    ... 81 more
Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'testLoanOrderController' method 
pl.smarttesting.loanorders.controller.LoanOrderController#findOrder(String)
to {GET /orders/{orderId}}: There is already 'loanOrderController' bean method
pl.smarttesting.loanorders.controller.LoanOrderController#findOrder(String) mapped.
    at org.springframework.web.reactive.result.method.AbstractHandlerMethodMapping$MappingRegistry.validateMethodMapping(AbstractHandlerMethodMapping.java:507)
    at org.springframework.web.reactive.result.method.AbstractHandlerMethodMapping$MappingRegistry.register(AbstractHandlerMethodMapping.java:485)
    at org.springframework.web.reactive.result.method.AbstractHandlerMethodMapping.registerHandlerMethod(AbstractHandlerMethodMapping.java:243)
    at org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping.registerHandlerMethod(RequestMappingHandlerMapping.java:272)
    at org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping.registerHandlerMethod(RequestMappingHandlerMapping.java:59)
    at org.springframework.web.reactive.result.method.AbstractHandlerMethodMapping.lambda$detectHandlerMethods$1(AbstractHandlerMethodMapping.java:213)
    at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:723)
    at org.springframework.web.reactive.result.method.AbstractHandlerMethodMapping.detectHandlerMethods(AbstractHandlerMethodMapping.java:211)
    at org.springframework.web.reactive.result.method.AbstractHandlerMethodMapping.initHandlerMethods(AbstractHandlerMethodMapping.java:189)
    at org.springframework.web.reactive.result.method.AbstractHandlerMethodMapping.afterPropertiesSet(AbstractHandlerMethodMapping.java:157)
    at org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping.afterPropertiesSet(RequestMappingHandlerMapping.java:126)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1853)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1790)
    ... 97 more
What I see in test execution logs is that the LoanOrdersApplication class is being resolved as a configuration to be used by the test
15:13:35.700 [main] DEBUG org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider - Identified candidate component class: file [/home/foo/bar/target/classes/a/LoanOrdersApplication.class]
15:13:35.701 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Found @SpringBootConfiguration a.LoanOrdersApplication for test class a.LoanOrderControllerTest
But this is strange cause according to the javadocs
If no explicit classes are defined the test will look for nested @Configuration classes, before falling back to a @SpringBootConfiguration search.
I did pass the explicit Configuration classes via the classes argument so I would assume that my configuration class would be resolved and the main one wouldn't be.
Either I'm doing sth wrong or the documentation & javadocs are wrong or there's a bug somewhere.
cc @snicoll
Comment From: snicoll
TL;DR @SpringBootTest(classes = LoanOrderControllerTest.ControllerWithFakeConfig.class) still detected the @SpringBootConfiguration rather than starting the context with only LoanOrderControllerTest.ControllerWithFakeConfig.class
Comment From: dreis2211
@marcingrzejszczak The javadoc of @TestConfiguration is more specific about this:
/**
 * ....Unlike regular {@code @Configuration} classes the use of
 * {@code @TestConfiguration} does not prevent auto-detection of
 * {@link SpringBootConfiguration @SpringBootConfiguration}.
 */
You can use @Configuration to workaround your issue, I guess. But I agree - the docs on @SpringBootTest#classes are a bit misleading and I stumbled upon this in the past as well.
Comment From: snicoll
@dreis2211 I am confused by the comment. The problem that's raised here is that specifying a classes attribute with a @Configuration does not prevent the auto-detection of @SpringBootConfiguration. 
Comment From: dreis2211
@snicoll isn't ControllerWithFakeConfig using @TestConfiguration? @Configuration would actually prevent it.
Comment From: snicoll
@dreis2211 funny. Marcin pasted the wrong example (we were trying several options offline). Marcin can you double check and update the example please?
Comment From: marcingrzejszczak
Actually when I make it @Configuration it works fine. However Stephane AFAIR you said that it didn't work for you.
Comment From: marcingrzejszczak
Ok let's close the issue for now cause it seems that things work fine.