💻 Exemplos: Capítulo 16: Testes Automatizados com @SpringBootTest, MockMvc e Testcontainers
Especialização em Backend com Java & Spring Boot • Demonstrações Práticas Compiláveis
💻 Código de Exemplo 01 — Slice Test de Controller com @WebMvcTest e Validação de Payload
package com.empresa.api.controller;
import com.empresa.api.service.PedidoService;
import com.fasterxml.jackson.databind.ObjectMapper;
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.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@WebMvcTest(PedidoController.class)
class PedidoControllerTest {
@Autowired private MockMvc mockMvc;
@Autowired private ObjectMapper objectMapper;
@MockBean private PedidoService pedidoService;
@Test
void deveCriarPedidoComStatus201() throws Exception {
var request = new NovoPedidoRequest("cliente-42", java.util.List.of("item-1"));
when(pedidoService.criar(any())).thenReturn(new PedidoDTO(10L, "PENDENTE"));
mockMvc.perform(post("/api/v1/pedidos")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.status").value("PENDENTE"));
verify(pedidoService).criar(any()); // confirma que o serviço foi de fato chamado
}
@Test
void deveRejeitarPedidoSemItensComStatus400() throws Exception {
var requestInvalido = new NovoPedidoRequest("cliente-42", java.util.List.of()); // @NotEmpty falha
mockMvc.perform(post("/api/v1/pedidos")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(requestInvalido)))
.andExpect(status().isBadRequest());
}
}
💻 Código de Exemplo 02 — Teste de Integração com Testcontainers e Banco Real
package com.empresa.api.repository;
import com.empresa.api.model.Cliente;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
@Testcontainers
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) // não usa H2 embutido
class ClienteRepositoryTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine");
@DynamicPropertySource
static void datasourceProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@Autowired private ClienteRepository clienteRepository;
@Test
void deveSalvarEBuscarClientePorEmailComDialetoPostgresReal() {
clienteRepository.save(new Cliente(null, "Maria Silva", "maria@empresa.com"));
var encontrado = clienteRepository.findByEmail("maria@empresa.com");
assertThat(encontrado).isPresent();
assertThat(encontrado.get().getNome()).isEqualTo("Maria Silva");
}
}
💻 Código de Exemplo 03 — Teste de Integração Ponta a Ponta com @SpringBootTest
package com.empresa.api;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.http.ResponseEntity;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class PedidoFluxoCompletoIntegrationTest {
@LocalServerPort
private int porta;
@Autowired
private TestRestTemplate restTemplate;
@Test
void deveExecutarFluxoRealDeCriacaoDePedidoComServidorEmbarcadoAtivo() {
var request = new NovoPedidoRequest("cliente-42", java.util.List.of("item-1", "item-2"));
ResponseEntity<PedidoDTO> resposta = restTemplate.postForEntity(
"http://localhost:" + porta + "/api/v1/pedidos", request, PedidoDTO.class);
assertThat(resposta.getStatusCode().is2xxSuccessful()).isTrue();
assertThat(resposta.getBody().status()).isEqualTo("PENDENTE");
}
}