@EnableAutoConfiguration не работает с @WebMvcTest. Почему?

Я обнаружил, что мне приходится вручную @Import классы автоконфигурации при использовании @WebMvcTest:

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.ServerResponse;

import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest(controllers = MyWebMvcTest.ComplimentingConfig.class)
@Import({GatewayServerMvcAutoConfiguration.class,
        SslAutoConfiguration.class,
        RestClientAutoConfiguration.class})
public class MyWebMvcTest {
    @Autowired
    MockMvc mockMvc;

    @Test
    void test() throws Exception {
        mockMvc.perform(get("/get"))
                .andExpect(status().isOk());
    }

    @Configuration
    static class ComplimentingConfig {
        @Bean
        public RouterFunction<ServerResponse> getRoute() {
            return route()
                    .GET("/get", http("https://httpbin.org/status/200"))
                    .build();
        }
    }
}

Если я решу импортировать конфигурацию с аннотацией @EnableAutoConfiguration и, таким образом, неявно включить этот импорт, я получу исключение, поскольку некоторые необходимые bean-компоненты отсутствуют в контексте.

@WebMvcTest(controllers = MyWebMvcTest.ComplimentingConfig.class)
@Import(MyWebMvcTest.ComplimentingConfig.class)
public class MyWebMvcTest {

// ...

    @Configuration
    @EnableAutoConfiguration
    static class ComplimentingConfig {
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.gateway.server.mvc.handler.ProxyExchangeHandlerFunction' available

Почему @EnableAutoConfiguration не работает с @WebMvcTest?

Java 17, Spring MVC 6.1.5, Spring Boot 3.2.4

Примечание. Я использовал Spring Cloud Gateway MVC в MRE выше, чтобы потребовать дополнительных @Import. Если бы я использовал простой RouterFuction (например, route().GET("/get", r -> ServerResponse.ok().build()).build()), весь вопрос был бы спорным, поскольку все необходимые компоненты были бы неявно предоставлены @WebMvcTest

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
78
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Насколько я понимаю, как работает Spring MVC. Spring пытается упростить и больше сосредотачивается на конкретном тестовом примере. Я имею в виду, что @WebMvcTest работает только в ограниченном контексте приложения, чтобы уменьшить количество несвязанных компонентов.

О Spring Cloud Gateway, который использует RouterFunction, использует автоконфигурацию для настройки необходимых компонентов, тогда как @WebMvcTest фокусируется только на Mvc и не включает все bean-компоненты, связанные со шлюзом.

Не слишком уверен в этом, но именно это я понял, когда в последний раз возился с этой темой.

Ответ принят как подходящий

Сначала вам нужно понять, что такое срезовое тестирование и интеграционное тестирование.

@WebMvcTest не запускает полный контекст приложения Spring. Он используется только для срезового тестирования веб-слоя. Он сканирует классы, помеченные знаком @Controller. Чтобы сузить список, вы можете указать имя контроллера, например @WebMvcTest(XyzController.class). Он часто сопровождается @MockBean, если ваш контроллер имеет ссылку на другой класс. Он не будет читать другие ваши конфигурации. Аналогично @DataJpaTest загружает @Repository занятия.

Теперь у вас осталось два варианта:

  1. @SpringBootTest — будет искать основной класс конфигурации (тот, который вы отметили @SpringBootApplication) и запускать контекст приложения Spring. Это вы можете использовать для своего интеграционного тестирования. Здесь вы определили, хотите ли вы использовать сервер или нет.

    @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
    class TestClass {}
    

    Это также запустит ваш сервер. Если вы этого не хотите, вы можете использовать

    @SpringBootTest
    @AutoConfigureMockMvc
    class TestClass {}
    
  2. @ContextConfiguration(classes = {XyzConfig.class}) — будут загружены только указанные конфигурации. Это будет ваше срезовое тестирование.

    @ExtendWith(SpringExtension.class)
    @ContextConfiguration(classes = {XyzConfig.class})
    class TestClass {}
    

Теперь вы можете решить, как вы хотите действовать.

Почему @EnableAutoConfiguration не работает с @WebMvcTest?

@WebMvcTest аннотация отключит полную автоматическую настройку и будет применять только конфигурацию, соответствующую тестам MVC, как я объяснил выше. Даже если вы явно упомянули автоконфигурацию, @WebMvcTest отменяет ее. Прочтите это

Спасибо! Хотя я все это знаю. С другой стороны, я не знаю, почему явная @Import работа работает, а извлечение @EnableAutoConfiguration-аннотированной конфигурации — нет (хотя оба, похоже, делают одно и то же)

Powet 13.04.2024 18:02

Обновил свой ответ. Аннотация @WebMvcTest отключит полную автоматическую настройку и применит только конфигурацию, соответствующую тестам MVC, как я объяснил в своем ответе. Надеюсь, теперь все ясно.

YogendraR 13.04.2024 18:33

Другие вопросы по теме