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");
    }
}