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.