Neste tutorial, vamos criar um aplicativo Spring Boot que permite realizar as operações básicas de CRUD (Create, Read, Update, Delete) para gerenciar informações de um usuário, mas seguindo a metodologia TDD. Ou seja, vamos escrever os testes primeiro e depois implementar as funcionalidades. Usaremos o JUnit 5 para os testes e o Mockito para simular dependências, garantindo que o código esteja funcionando corretamente antes de ser implementado.
Preparando o Ambiente
Requisitos
Antes de começarmos, é necessário garantir que temos o ambiente adequado configurado:
- Java: Instale o JDK 11 ou superior.
- IDE: Recomendo usar o Spring Tool Suite (STS), mas você pode usar qualquer IDE de sua escolha.
- Maven: Spring Boot já inclui o Maven, mas você pode instalá-lo separadamente.
- Banco de Dados: Instale o MySQL ou qualquer outro banco de dados relacional de sua preferência.
Dependências Necessárias
- JUnit 5 para testes.
- Mockito para simular objetos e dependências.
- Spring Boot Test para realizar os testes de integração.
No arquivo pom.xml
, adicione as dependências de testes:
<dependencies>
<!-- Spring Boot Starter Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Estrutura do Projeto
O projeto terá a seguinte estrutura:
- src/main/java/com/exemplo/crudusuario: Código-fonte da aplicação.
- Controller: Controlador REST.
- Service: Lógica de negócios.
- Model: Entidade de Usuário.
- Repository: Repositório JPA.
- src/test/java/com/exemplo/crudusuario: Testes de unidade e integração.
- Controller: Testes do controlador.
- Service: Testes do serviço.
Passo 1: Escrevendo o Primeiro Teste – Testando a Criação de um Usuário
Comece criando o teste para a criação de um novo usuário. Vamos escrever o teste antes de criar o código da funcionalidade.
Teste de Criação de Usuário
No diretório de testes, crie um arquivo chamado UsuarioServiceTest.java
.
package com.exemplo.crudusuario;
import com.exemplo.crudusuario.model.Usuario;
import com.exemplo.crudusuario.repository.UsuarioRepository;
import com.exemplo.crudusuario.service.UsuarioService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
class UsuarioServiceTest {
@InjectMocks
private UsuarioService usuarioService;
@Mock
private UsuarioRepository usuarioRepository;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
@Test
void testCriarUsuario() {
// Criar um objeto de teste
Usuario usuario = new Usuario();
usuario.setNome("João Silva");
usuario.setEmail("joao@exemplo.com");
usuario.setSenha("senha123");
// Simular o comportamento do repositório
when(usuarioRepository.save(any(Usuario.class))).thenReturn(usuario);
// Chamar o método a ser testado
Usuario usuarioCriado = usuarioService.salvarUsuario(usuario);
// Verificar os resultados
assertNotNull(usuarioCriado);
assertEquals("João Silva", usuarioCriado.getNome());
assertEquals("joao@exemplo.com", usuarioCriado.getEmail());
assertEquals("senha123", usuarioCriado.getSenha());
// Verificar se o repositório foi chamado
verify(usuarioRepository, times(1)).save(usuario);
}
}
Explicação do Teste:
- @Mock: Usamos o Mockito para simular o comportamento do repositório.
- @InjectMocks: Spring irá injetar o serviço
UsuarioService
, onde vamos usar o repositório simulado. - when(…).thenReturn(…): Simula a resposta do repositório quando o método
save()
for chamado. - verify(…, times(1)): Verifica se o repositório foi chamado uma vez.
Passo 2: Implementando o Serviço de Usuário
Agora que temos o teste para a criação de um usuário, podemos implementar a classe UsuarioService
.
Classe UsuarioService
package com.exemplo.crudusuario.service;
import com.exemplo.crudusuario.model.Usuario;
import com.exemplo.crudusuario.repository.UsuarioRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UsuarioService {
@Autowired
private UsuarioRepository usuarioRepository;
public Usuario salvarUsuario(Usuario usuario) {
return usuarioRepository.save(usuario);
}
public List<Usuario> listarUsuarios() {
return usuarioRepository.findAll();
}
public Usuario obterUsuarioPorId(Long id) {
return usuarioRepository.findById(id).orElse(null);
}
public void excluirUsuario(Long id) {
usuarioRepository.deleteById(id);
}
}
Passo 3: Escrevendo os Testes para o Controlador
Agora vamos escrever os testes para o controlador, que expõe as APIs REST.
Teste do Controlador de Usuário
Crie um arquivo chamado UsuarioControllerTest.java
no diretório de testes.
package com.exemplo.crudusuario;
import com.exemplo.crudusuario.controller.UsuarioController;
import com.exemplo.crudusuario.model.Usuario;
import com.exemplo.crudusuario.service.UsuarioService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
class UsuarioControllerTest {
private MockMvc mockMvc;
@InjectMocks
private UsuarioController usuarioController;
@Mock
private UsuarioService usuarioService;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(usuarioController).build();
}
@Test
void testCriarUsuario() throws Exception {
// Criar um objeto de teste
Usuario usuario = new Usuario();
usuario.setNome("João Silva");
usuario.setEmail("joao@exemplo.com");
usuario.setSenha("senha123");
// Simular o comportamento do serviço
when(usuarioService.salvarUsuario(any(Usuario.class))).thenReturn(usuario);
// Realizar a requisição POST
mockMvc.perform(post("/usuarios")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"nome\":\"João Silva\", \"email\":\"joao@exemplo.com\", \"senha\":\"senha123\"}"))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.nome").value("João Silva"))
.andExpect(jsonPath("$.email").value("joao@exemplo.com"));
}
}
Explicação do Teste:
- MockMvc: Utilizado para simular uma requisição HTTP.
- when(…).thenReturn(…): Simula o retorno do serviço.
- jsonPath(…): Verifica se o JSON retornado contém os valores esperados.
Passo 4: Implementando o Controlador
Agora que temos os testes, podemos implementar o controlador para expor a API REST.
Classe UsuarioController
package com.exemplo.crudusuario.controller;
import com.exemplo.crudusuario.model.Usuario;
import com.exemplo.crudusuario.service.UsuarioService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/usuarios")
public class UsuarioController {
@Autowired
private UsuarioService usuarioService;
@PostMapping
public ResponseEntity<Usuario> criarUsuario(@RequestBody Usuario usuario) {
Usuario savedUsuario = usuarioService.salvarUsuario(usuario);
return ResponseEntity.status(HttpStatus.CREATED).body(savedUsuario);
}
@GetMapping
public List<Usuario> listarUsuarios() {
return usuarioService.listarUsuarios();
}
@GetMapping("/{id}")
public ResponseEntity<Usuario> obterUsuario(@PathVariable Long id) {
Usuario usuario = usuarioService.obterUsuarioPorId(id);
return usuario != null ? ResponseEntity.ok(usuario) : ResponseEntity.notFound().build();
}
@PutMapping("/{id}")
public ResponseEntity<Usuario> atualizarUsuario(@PathVariable Long id, @RequestBody Usuario usuario) {
usuario.setId(id);
Usuario updatedUsuario = usuarioService.salvarUsuario(usuario);
return ResponseEntity.ok(updatedUsuario);
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> excluirUsuario(@PathVariable Long id) {
usuarioService.excluirUsuario(id);
return ResponseEntity.noContent().build();
}
}
Passo 5: Rodando os Testes
Agora que todas as classes e testes estão implementados, basta rodar os testes com o comando:
mvn test
Conclusão
Neste tutorial, aprendemos como criar um CRUD de usuários utilizando Spring Boot e a abordagem TDD (Test-Driven Development). Escrevemos os testes antes da implementação das funcionalidades, garantindo que o código seja testável e de alta qualidade.
Com isso, você agora pode aplicar TDD em seus projetos Spring Boot para garantir que seu código seja confiável desde o início!
Deixe um comentário