WebAppConfiguration em testes de primavera

WebAppConfiguration em testes de primavera

1. Visão geral

Neste artigo, vamos explorar a anotação@WebAppConfiguration no Spring, por que precisamos dela em nossos testes de integração e também como podemos configurá-la para que esses testes realmente inicializem aWebApplicationContext.

2. @WebAppConfiguration

Simplificando, essa é uma anotação em nível de classe usada para criar uma versão da Web do contexto do aplicativo no Spring Framework.

É usado para denotar queApplicationContext que é inicializado para o teste deve ser uma instância deWebApplicationContext.

Uma nota rápida sobre o uso - geralmente encontraremos essa anotação em testes de integração porqueWebApplicationContext é usado para construir um objetoMockMvc. Você pode encontrar mais informações sobre o teste de integração com Springhere.

3. Carregando umWebApplicationContext

A partir do Spring 3.2, agora há suporte para carregar aWebApplicationContext em testes de integração:

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

Isso instrui a estruturaTestContext que umWebApplicationContext deve ser carregado para o teste.

E, em segundo plano, umMockServletContext é criado e fornecido aoWebApplicationContext do nosso teste pela estruturaTestContext.

3.1. Opções de configuração

Por padrão, o caminho do recurso base paraWebApplicationContext será definido como“file:src/main/webapp”,, que é o local padrão para a raiz do WAR em um Projeto Maven.

No entanto, podemos substituir isso simplesmente fornecendo um caminho alternativo para a anotação@WebAppConfiguration:

@WebAppConfiguration("src/test/webapp")

Também podemos fazer referência a um caminho de recurso base no caminho de classe, em vez do sistema de arquivos:

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

3.2. Armazenamento em cache

Assim queWebApplicationContext for carregado, ele será armazenado em cache e reutilizado para todos os testes subsequentes que declaram a mesma configuração de contexto exclusiva dentro do mesmo conjunto de testes.

Para obter mais detalhes sobre o cache, você pode consultar a seçãoContext caching do manual de referência.

4. Usando@WebAppConfiguration em testes

Agora que entendemos por que precisamos adicionar a anotação@WebAppConfiguration em nossas classes de teste, vamos verwhat happens if we miss adding it quando estamos usando umWebApplicationContext.

@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();
    }

    ...
}

Observe que comentamos a anotação para simular o cenário em que esquecemos de adicioná-la. Aqui é fácil ver por que o teste falhará quando executamos o teste JUnit:we are trying to autowire the WebApplicationContext in a class where we haven’t set one.

Um exemplo mais típico, entretanto, é um teste que usa uma configuração Spring habilitada para web; isso é realmente o suficiente para fazer o teste quebrar.

Vamos dar uma olhada:

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

    @Autowired
    private EmployeeController employeeController;

    ...
}

Mesmo que o exemplo acima não esteja conectando automaticamente umWebApplicationContext, ele ainda falhará porque está tentando usar uma configuração habilitada para web -WebConfig:

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

A anotação@EnableWebMvc é a culpada aqui - isso basicamente exigirá um contexto Spring habilitado para web e, sem ele, veremos o teste falhar:

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

Então esse é o problema que estamos corrigindo facilmente adicionando a anotação@WebAppConfiguration aos nossos testes.

5. Conclusão

Neste artigo, mostramos como podemos permitir que o frameworkTestContext carregue umWebApplicationContext em nossos testes de integração apenas adicionando a anotação.

Finalmente, vimos os exemplos de que, embora adicionemos @ContextConfiguration ao teste, isso não funcionará a menos que adicionemos a anotação@WebAppConfiguration.

A implementação dos exemplos neste artigo estão disponíveis em nosso repositório emGitHub.