«1. Обзор

В этой статье мы рассмотрим аннотацию @WebAppConfiguration в Spring, зачем она нам нужна в наших интеграционных тестах, а также как мы можем настроить ее, чтобы эти тесты фактически загружали WebApplicationContext.

2. @WebAppConfiguration

Проще говоря, это аннотация уровня класса, используемая для создания веб-версии контекста приложения в Spring Framework.

Используется для обозначения того, что ApplicationContext, загружаемый для теста, должен быть экземпляром WebApplicationContext.

Небольшое примечание об использовании — обычно мы находим эту аннотацию в интеграционных тестах, потому что WebApplicationContext используется для создания объекта MockMvc. Дополнительную информацию об интеграционном тестировании с Spring можно найти здесь.

3. Загрузка WebApplicationContext

Начиная с Spring 3.2 теперь поддерживается загрузка WebApplicationContext в интеграционных тестах:

@WebAppConfiguration
@ContextConfiguration(classes = WebConfig.class)
public class EmployeeControllerTest {
    ...
}

Это указывает платформе TestContext, что WebApplicationContext должен быть загружен для теста.

И в фоновом режиме создается MockServletContext, который передается в WebApplicationContext нашего теста фреймворком TestContext.

3.1. Параметры конфигурации

По умолчанию базовый путь к ресурсу для WebApplicationContext будет установлен на «file:src/main/webapp», что является расположением по умолчанию для корня WAR в проекте Maven.

Однако мы можем переопределить это, просто указав альтернативный путь к аннотации @WebAppConfiguration:

@WebAppConfiguration("src/test/webapp")

Мы также можем ссылаться на путь к базовому ресурсу из пути к классам вместо файловой системы:

@WebAppConfiguration("classpath:test-web-resources")

3.2. Кэширование

После загрузки WebApplicationContext он будет кэширован и повторно использован для всех последующих тестов, которые объявляют ту же уникальную конфигурацию контекста в одном и том же наборе тестов.

Дополнительные сведения о кэшировании см. в разделе Кэширование контекста справочного руководства.

4. Использование @WebAppConfiguration в тестах

Теперь, когда мы понимаем, зачем нам нужно добавлять аннотацию @WebAppConfiguration в наши тестовые классы, давайте посмотрим, что произойдет, если мы пропустим ее добавление при использовании WebApplicationContext.

@RunWith(SpringJUnit4ClassRunner.class)
// @WebAppConfiguration omitted on purpose
@ContextConfiguration(classes = WebConfig.class)
public class EmployeeTest {

    @Autowired
    private WebApplicationContext webAppContext;
    private MockMvc mockMvc;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext).build();
    }
    
    ...
}

Обратите внимание, что мы закомментировали аннотацию, чтобы имитировать сценарий, в котором мы забыли добавить ее. Здесь легко понять, почему тест провалится, когда мы запустим тест JUnit: мы пытаемся автоматически связать WebApplicationContext в классе, где мы его не установили.

Однако более типичным примером является тест, в котором используется веб-конфигурация Spring; этого на самом деле достаточно, чтобы сделать тестовый перерыв.

Давайте посмотрим:

@RunWith(SpringJUnit4ClassRunner.class)
// @WebAppConfiguration omitted on purpose
@ContextConfiguration(classes = WebConfig.class)
public class EmployeeTestWithoutMockMvc {

    @Autowired
    private EmployeeController employeeController;

    ...
}

Несмотря на то, что приведенный выше пример не выполняет автоматическое связывание WebApplicationContext, он все равно завершится ошибкой, потому что он пытается использовать веб-конфигурацию – WebConfig:

@Configuration
@EnableWebMvc
@ComponentScan("com.baeldung.web")
public class WebConfig implements WebMvcConfigurer {
    ...
}

Виновником здесь является аннотация @EnableWebMvc — для этого в основном потребуется контекст Spring с веб-поддержкой, а без него — мы увидим, что тест не пройден:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: 
  No qualifying bean of type [javax.servlet.ServletContext] found for dependency: 
    expected at least 1 bean which qualifies as autowire candidate for this dependency. 

Dependency annotations: 
  {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at o.s.b.f.s.DefaultListableBeanFactory
      .raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373)
    at o.s.b.f.s.DefaultListableBeanFactory
      .doResolveDependency(DefaultListableBeanFactory.java:1119)
    at o.s.b.f.s.DefaultListableBeanFactory
      .resolveDependency(DefaultListableBeanFactory.java:1014)
    at o.s.b.f.a.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement
      .inject(AutowiredAnnotationBeanPostProcessor.java:545)
    ... 43 more

Так что это проблема, которую мы легко исправление путем добавления аннотации @WebAppConfiguration в наши тесты.

5. Заключение

В этой статье мы показали, как мы можем позволить платформе TestContext загружать WebApplicationContext в наши интеграционные тесты, просто добавив аннотацию.

Наконец, мы рассмотрели примеры того, что даже если мы добавим @ContextConfiguration в тест, это не сможет работать, пока мы не добавим аннотацию @WebAppConfiguration.

Реализация примеров из этой статьи доступна в нашем репозитории на GitHub.