Introdução

Neste tutorial, você aprenderá como aplicar práticas de desenvolvimento ágil utilizando o framework Red, focando na implementação de testes automatizados para garantir a qualidade e a eficiência do seu software. O desenvolvimento ágil permite que as equipes de desenvolvimento estejam mais adaptativas às mudanças de requisitos e entregas mais rápidas. Neste artigo, abordaremos desde a configuração do ambiente até a criação, teste e validação de um projeto completo em Java com Spring Boot, aplicando conceitos de testes automatizados para garantir que as funcionalidades implementadas atendam às expectativas e requisitos do negócio. Com os exemplos práticos, você se sentirá mais confiante em adotar esse modelo de desenvolvimento. Vamos começar!

Etapas

  1. Configuração do Ambiente de Desenvolvimento

    Antes de começar, verifique se você possui o JDK (Java Development Kit) e o Maven instalados em sua máquina. Você pode fazer isso executando os comandos a seguir no terminal:

    commands
    # Verificar versões instaladas
    java -version
    mvn -version

  2. Criação do Projeto Spring Boot

    Utilize o Spring Initializr para gerar um novo projeto Spring Boot com as dependências necessárias. Configure o projeto com as seguintes opções: **Project**: Maven, **Language**: Java, **Spring Boot**: última versão estável, **Packaging**: Jar, **Java**: 11 ou superior. Adicione as dependências ‘Spring Web’, ‘Spring Data JPA’, e ‘H2 Database’. Baixe e descompacte o projeto em seu ambiente de trabalho.

    pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.example</groupId>
      <artifactId>api-qualidade-software</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <name>api-qualidade-software</name>
      <description>API para teste de qualidade de software</description>
      <properties>
        <java.version>11</java.version>
      </properties>
      <dependencies>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
          <groupId>com.h2database</groupId>
          <artifactId>h2</artifactId>
          <scope>runtime</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
        </dependency>
      </dependencies>
      <build>
        <plugins>
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>
        </plugins>
      </build>
    </project>

  3. Configuração do Banco de Dados H2

    Edite o arquivo `application.properties` para definir as propriedades do banco de dados H2 e habilitar o console web para visualização dos dados.

    application.properties
    spring.h2.console.enabled=true
    spring.datasource.url=jdbc:h2:mem:testdb
    spring.datasource.driverClassName=org.h2.Driver
    spring.datasource.username=sa
    spring.datasource.password=
    spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
    spring.jpa.hibernate.ddl-auto=update

  4. Criação da Entidade `Usuario`

    Implemente a classe modelo `Usuario` que representará os usuários na aplicação. Use anotações JPA para mapear a classe à tabela do banco de dados.

    Usuario.java
    package com.example.apiqualidadesoftware.model;
    
    import javax.persistence.*;
    
    @Entity
    @Table(name = "usuarios")
    public class Usuario {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(nullable = false)
        private String nome;
    
        @Column(nullable = false, unique = true)
        private String email;
    
        // Getters e Setters
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getNome() {
            return nome;
        }
    
        public void setNome(String nome) {
            this.nome = nome;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    }
    

  5. Criação do Repositório `UsuarioRepository`

    Implemente a interface `UsuarioRepository`, que estende `JpaRepository` e fornece métodos CRUD.

    UsuarioRepository.java
    package com.example.apiqualidadesoftware.repository;
    
    import com.example.apiqualidadesoftware.model.Usuario;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface UsuarioRepository extends JpaRepository<Usuario, Long> {
        // Métodos personalizados podem ser definidos aqui, se necessário
    }
    

  6. Implementação do Serviço `UsuarioService`

    Crie a classe `UsuarioService`, que contém a lógica de negócios e utiliza o `UsuarioRepository` para interagir com o banco de dados.

    UsuarioService.java
    package com.example.apiqualidadesoftware.service;
    
    import com.example.apiqualidadesoftware.model.Usuario;
    import com.example.apiqualidadesoftware.repository.UsuarioRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    import java.util.Optional;
    
    @Service
    public class UsuarioService {
        @Autowired
        private UsuarioRepository usuarioRepository;
    
        public List<Usuario> findAll() {
            return usuarioRepository.findAll();
        }
    
        public Optional<Usuario> findById(Long id) {
            return usuarioRepository.findById(id);
        }
    
        public Usuario save(Usuario usuario) {
            return usuarioRepository.save(usuario);
        }
    
        public Usuario update(Long id, Usuario usuarioDetails) {
            Usuario usuario = usuarioRepository.findById(id).orElseThrow(() -> new RuntimeException("Usuário não encontrado"));
            usuario.setNome(usuarioDetails.getNome());
            usuario.setEmail(usuarioDetails.getEmail());
            return usuarioRepository.save(usuario);
        }
    
        public void deleteById(Long id) {
            usuarioRepository.deleteById(id);
        }
    }
    

  7. Implementação do Controlador `UsuarioController`

    Crie a classe `UsuarioController` para expor os endpoints da API, permitindo operações CRUD.

    UsuarioController.java
    package com.example.apiqualidadesoftware.controller;
    
    import com.example.apiqualidadesoftware.model.Usuario;
    import com.example.apiqualidadesoftware.service.UsuarioService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    @RestController
    @RequestMapping("/api/usuarios")
    public class UsuarioController {
        @Autowired
        private UsuarioService usuarioService;
    
        @GetMapping
        public List<Usuario> getAllUsuarios() {
            return usuarioService.findAll();
        }
    
        @GetMapping("/{id}")
        public ResponseEntity<Usuario> getUsuarioById(@PathVariable Long id) {
            return usuarioService.findById(id)
                    .map(ResponseEntity::ok)
                    .orElse(ResponseEntity.notFound().build());
        }
    
        @PostMapping
        public Usuario createUsuario(@RequestBody Usuario usuario) {
            return usuarioService.save(usuario);
        }
    
        @PutMapping("/{id}")
        public ResponseEntity<Usuario> updateUsuario(@PathVariable Long id, @RequestBody Usuario usuarioDetails) {
            return ResponseEntity.ok(usuarioService.update(id, usuarioDetails));
        }
    
        @DeleteMapping("/{id}")
        public ResponseEntity<Void> deleteUsuario(@PathVariable Long id) {
            usuarioService.deleteById(id);
            return ResponseEntity.noContent().build();
        }
    }
    

  8. Implementação de Testes Unitários

    Crie a classe de testes `UsuarioServiceTest` para validar a lógica de negócios e operações CRUD da aplicação.

    UsuarioServiceTest.java
    package com.example.apiqualidadesoftware.service;
    
    import com.example.apiqualidadesoftware.model.Usuario;
    import com.example.apiqualidadesoftware.repository.UsuarioRepository;
    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 java.util.Arrays;
    import java.util.List;
    import java.util.Optional;
    
    import static org.junit.jupiter.api.Assertions.*;
    import static org.mockito.Mockito.*;
    
    public class UsuarioServiceTest {
        @InjectMocks
        private UsuarioService usuarioService;
    
        @Mock
        private UsuarioRepository usuarioRepository;
    
        @BeforeEach
        public void init() {
            MockitoAnnotations.openMocks(this);
        }
    
        @Test
        public void testFindAll() {
            Usuario usuario1 = new Usuario();
            usuario1.setId(1L);
            usuario1.setNome("Usuário 1");
            usuario1.setEmail("usuario1@example.com");
    
            Usuario usuario2 = new Usuario();
            usuario2.setId(2L);
            usuario2.setNome("Usuário 2");
            usuario2.setEmail("usuario2@example.com");
    
            when(usuarioRepository.findAll()).thenReturn(Arrays.asList(usuario1, usuario2));
    
            List<Usuario> usuarios = usuarioService.findAll();
            assertEquals(2, usuarios.size());
            verify(usuarioRepository, times(1)).findAll();
        }
    
        // Testes adicionais para os métodos findById, save, update e deleteById
    }
    

  9. Executando a Aplicação e Testes

    Use o Maven para compilar e executar a aplicação. Em seguida, utilize ferramentas como Postman ou cURL para testar os endpoints da API.

    commands
    # Compilar e executar a aplicação
    mvn spring-boot:run
    # Executar os testes unitários
    mvn test

    curl_examples
    # Listar todos os usuários
    curl -X GET http://localhost:8080/api/usuarios
    # Criar um novo usuário
    curl -X POST -H "Content-Type: application/json" -d '{"nome":"Novo Usuário", "email":"novo.usuário@example.com"}' http://localhost:8080/api/usuarios

Conclusão

Neste tutorial, você aprendeu a criar uma API RESTful com Spring Boot, cobrindo desde a configuração inicial do ambiente até a implementação da lógica de negócios, expostos via um controlador. Além disso, exploramos a importância dos testes automatizados para garantir a qualidade do software. Com essas práticas, você pode agora construir aplicações mais robustas e confiáveis, além de estar mais preparado para lidar com ambientes de desenvolvimento ágil. Continue explorando as funcionalidades do Spring Boot e buscando melhorar suas habilidades em desenvolvimento de software!

Hashtags

#Java #SpringBoot #DesenvolvimentoÁgil #TestesAutomatizados #QualidadeDeSoftware #DesenvolvimentoDeSoftware