Teste de integração no Spring

Teste de integração no Spring

1. Visão geral

O teste de integração desempenha um papel importante no ciclo de desenvolvimento de aplicativos, verificando o comportamento de ponta a ponta do sistema.

Neste artigo, veremos como podemos aproveitar a estrutura de teste do Spring MVC para escrever e executar testes de integração que testam controladores sem iniciar explicitamente um contêiner de Servlet.

2. Preparação

As seguintes dependências do Maven são necessárias para executar os testes de integração, conforme descrito neste artigo. Em primeiro lugar, as dependênciasJUnit eSpring test mais recentes:


    junit
    junit
    4.12
    test


    org.springframework
    spring-test
    4.3.2.RELEASE
    test

Para uma afirmação eficaz dos resultados, também usaremosHamcresteJSON path:


    org.hamcrest
    hamcrest-library
    1.3
    test


    com.jayway.jsonpath
    json-path
    2.2.0
    test

3. Configuração de teste Spring MVC

Vamos agora apresentar como configurar e executar os testes habilitados para Spring.

3.1. Habilitar Spring em testes

Primeiro, qualquer teste habilitado para Spring será executado com a ajuda de@RunWith(SpringJUnit4ClassRunner.class); o runner é essencialmente o ponto de entrada para começar a usar a estrutura Spring Test.

Também precisamos das anotações@ContextConfiguration para carregar a configuração de contexto ebootstrap the context that the test will use.

Vamos dar uma olhada:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { ApplicationConfig.class })
@WebAppConfiguration
public class GreetControllerIntegrationTest {
    ....
}

Observe como, em@ContextConfiguration,, fornecemos a classe de configuraçãoApplicationConfig.class que carrega a configuração necessária para este teste específico.

Usamos uma classe de configuração Java aqui para especificar a configuração de contexto; Da mesma forma, podemos usar a configuração baseada em XML:

@ContextConfiguration(locations={""})

Finalmente - o teste também é anotado com@WebAppConfiguration – which will load the web application context.

Por padrão, ele procura o aplicativo da web raiz no caminho padrãosrc/main/webapp; o local pode ser substituído passando o argumento de valor como:

@WebAppConfiguration(value = "")

3.2. O objetoWebApplicationContext

WebApplicationContext (wac) fornece a configuração do aplicativo da web. Carrega todos os beans e controladores de aplicativos no contexto.

Agora seremos capazes de conectar o contexto do aplicativo da web direto ao teste:

@Autowired
private WebApplicationContext wac;

3.3. Simulando Beans de Contexto da Web

MockMvc fornece suporte para teste Spring MVC. Ele encapsula todos os beans de aplicativos da web e os disponibiliza para teste.

Vamos ver como usá-lo:

private MockMvc mockMvc;
@Before
public void setup() throws Exception {
    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}

Precisamos inicializar o objetomockMvc no método anotado@Before, para que não precisemos inicializá-lo dentro de cada teste.

3.4. Verifique a configuração do teste

Para nosso tutorial aqui, vamos realmente verificar se estamos carregando o objetoWebApplicationContext (wac) corretamente. Também verificaremos se oservletContext correto está sendo anexado:

@Test
public void givenWac_whenServletContext_thenItProvidesGreetController() {
    ServletContext servletContext = wac.getServletContext();

    Assert.assertNotNull(servletContext);
    Assert.assertTrue(servletContext instanceof MockServletContext);
    Assert.assertNotNull(wac.getBean("greetController"));
}

Observe que também estamos verificando se existe um beanGreetController.java no contexto da web - o que garante que os Spring beans sejam carregados corretamente.

Neste ponto, a configuração do teste de integração está concluída. Vamos ver como podemos testar métodos de recursos usando o objetoMockMvc.

4. Escrevendo testes de integração

Nesta seção, examinaremos a operação básica disponível por meio da estrutura de teste.

Mostraremos como enviar solicitações com variáveis ​​e parâmetros de caminho. Além disso, seguiremos com alguns exemplos que mostram como afirmar que o nome da visualização adequado foi resolvido ou que o corpo da resposta é o esperado.

Os fragmentos a seguir usam importações estáticas de classes MockMvcRequestBuilders ouMockMvcResultMatchers.

4.1. Verifique o nome da vista

Vamos invocar o endpoint/homePage do nosso teste como:

http://localhost:8080/spring-mvc-test/

or

http://localhost:8080/spring-mvc-test/homePage

Fragmento de código:

@Test
public void givenHomePageURI_whenMockMVC_thenReturnsIndexJSPViewName() {
    this.mockMvc.perform(get("/homePage")).andDo(print())

      .andExpect(view().name("index"));
}

Vamos decompô-lo:

  • O métodoperform() chamará um método de solicitação get que retornaResultActions. Usando esse resultado, podemos ter expectativas de afirmação em resposta como conteúdo, status HTTP, cabeçalho, etc.

  • andDo(print()) imprimirá a solicitação e a resposta. Isso é útil para obter uma visão detalhada em caso de erro

  • andExpect() esperará o argumento fornecido. Em nosso caso, esperamos que o "índice" seja retornado por meio deMockMvcResultMatchers.view()

4.2. Verificar corpo da resposta

Vamos invocar o endpoint/greet do nosso teste como:

http://localhost:8080/spring-mvc-test/greet

Saída esperada:

{
    "id": 1,
    "message": "Hello World!!!"
}

Fragmento de código:

@Test
public void givenGreetURI_whenMockMVC_thenVerifyResponse() {
    MvcResult mvcResult = this.mockMvc.perform(get("/greet"))
      .andDo(print()).andExpect(status().isOk())
      .andExpect(jsonPath("$.message").value("Hello World!!!"))
      .andReturn();

    Assert.assertEquals("application/json;charset=UTF-8",
      mvcResult.getResponse().getContentType());
}

Vamos ver exatamente o que está acontecendo:

  • andExpect(MockMvcResultMatchers.status().isOk()) verificará se o status http da resposta éOk, ou seja, 200. Isso garante que a solicitação foi executada com sucesso

  • andExpect(MockMvcResultMatchers.jsonPath(“$.message”).value(“Hello World!!!”)) verificará se o conteúdo da resposta corresponde ao argumento “Hello World!!!“. Aqui usamosjsonPath que extrai o conteúdo da resposta e fornece o valor solicitado

  • andReturn() retornará o objetoMvcResult que é usado, quando temos que verificar algo que não é alcançável pela biblioteca. Você pode ver que adicionamosassertEquals para corresponder ao tipo de conteúdo da resposta que é extraído do objetoMvcResult

4.3. Enviar solicitaçãoGET com variável de caminho

Vamos invocar o endpoint/greetWithPathVariable/{name} do nosso teste como:

http://localhost:8080/spring-mvc-test/greetWithPathVariable/John

Saída esperada:

{
    "id": 1,
    "message": "Hello World John!!!"
}

Fragmento de código:

@Test
public void givenGreetURIWithPathVariable_whenMockMVC_thenResponseOK() {
    this.mockMvc
      .perform(get("/greetWithPathVariable/{name}", "John"))
      .andDo(print()).andExpect(status().isOk())

      .andExpect(content().contentType("application/json;charset=UTF-8"))
      .andExpect(jsonPath("$.message").value("Hello World John!!!"));
}

MockMvcRequestBuilders.get(“/greetWithPathVariable/{name}”, “John”) enviará a solicitação como “/greetWithPathVariable/John“.

Isso se torna mais fácil com relação à legibilidade e ao saber quais são os parâmetros que são definidos dinamicamente no URL. Este método não se restringe a passar vários parâmetros de caminho.

4.4. Enviar solicitaçãoGET com parâmetros de consulta

Vamos invocar o endpoint/greetWithQueryVariable?name={name} do nosso teste como:

http://localhost:8080/spring-mvc-test
  /greetWithQueryVariable?name=John%20Doe

Saída esperada:

{
    "id": 1,
    "message": "Hello World John Doe!!!"
}

Fragmento de código:

@Test
public void givenGreetURIWithQueryParameter_whenMockMVC_thenResponseOK() {
    this.mockMvc.perform(get("/greetWithQueryVariable")
      .param("name", "John Doe")).andDo(print()).andExpect(status().isOk())
      .andExpect(content().contentType("application/json;charset=UTF-8"))
      .andExpect(jsonPath("$.message").value("Hello World John Doe!!!"));
}

param(“name”, “John Doe”) acrescentará o parâmetro de consulta na solicitaçãoGET. É semelhante a “/greetWithQueryVariable?name=John%20Doe“.

O parâmetro de consulta também pode ser implementado usando o estilo de modelo de URI:

this.mockMvc.perform(
  get("/greetWithQueryVariable?name={name}", "John Doe"));

4.5. Enviar pedidoPOST

Vamos invocar o endpoint/greetWithPost do nosso teste como:

http://localhost:8080/spring-mvc-test/greetWithPost

Saída esperada:

{
    "id": 1,
    "message": "Hello World!!!"
}

Fragmento de código:

@Test
public void givenGreetURIWithPost_whenMockMVC_thenVerifyResponse() {
    this.mockMvc.perform(post("/greetWithPost")).andDo(print())
      .andExpect(status().isOk()).andExpect(content()
      .contentType("application/json;charset=UTF-8"))
      .andExpect(jsonPath("$.message").value("Hello World!!!"));
}

MockMvcRequestBuilders.post(“/greetWithPost”) enviará a solicitação de postagem. Variáveis ​​de caminho e Parâmetros de consulta podem ser configurados da mesma forma que vimos anteriormente, enquanto os dados de formulário podem ser configurados por meio do métodoparam() apenas semelhante ao parâmetro de consulta como:

http://localhost:8080/spring-mvc-test/greetWithPostAndFormData

Dados do formulário:

id=1;name=John%20Doe

Saída esperada:

{
    "id": 1,
    "message": "Hello World John Doe!!!"
}

Fragmento de código:

@Test
public void givenGreetURIWithPostAndFormData_whenMockMVC_thenResponseOK() {
    this.mockMvc.perform(post("/greetWithPostAndFormData").param("id", "1")
      .param("name", "John Doe")).andDo(print()).andExpect(status().isOk())

      .andExpect(content().contentType("application/json;charset=UTF-8"))
      .andExpect(jsonPath("$.message").value("Hello World John Doe!!!"))
      .andExpect(jsonPath("$.id").value(1));
}

No snippet de código acima, adicionamos 2 parâmetros id como "1" e nome como "John Doe".

5. Conclusão

Neste tutorial rápido, implementamos alguns testes simples de integração habilitados para Spring.

Também observamos a criação de objetosWebApplicationContexteMockMVC, que desempenhou um papel importante na chamada dos terminais do aplicativo.

Olhando mais adiante, cobrimos como podemos enviar solicitaçõesGETePOST com variações de passagem de parâmetro e como verificar o status da resposta HTTP, cabeçalho e conteúdo.

Finalmente, a implementação de todos esses exemplos e trechos de código está disponível emhttps://github.com/eugenp/tutorials/tree/master/spring-mvc-java.