enunciados-exercicios-java

Exercício Java: Movepass

Logo Movepass

Neste exercício, você desenvolverá uma API REST utilizando Java e Spring Boot, com foco na criação de um sistema simples chamado Movepass. Este sistema é inspirado no Gympass, e será utilizado para praticar conceitos de Programação Orientada a Objetos (POO), testes, Spring Boot, e boas práticas de desenvolvimento de software.

Voltar

Índice

1. Introdução

O projeto Movepass consiste em uma API REST que simula a gestão de academias, empresas e assinaturas de funcionários. A ideia central é permitir que empresas possam cadastrar seus funcionários em academias, gerenciando assinaturas e possibilitando que esses funcionários utilizem as academias parceiras.

Você precisará implementar quatro principais entidades: Empresa, Funcionário, Academia e Assinatura. A regra de negócio básica é que uma empresa pode ter múltiplos funcionários, cada funcionário pode ter uma assinatura em uma ou mais academias, e cada academia pode ter vários funcionários assinantes.

2. Dependências

Dependências de um projeto são bibliotecas externas ou módulos que o projeto precisa para funcionar corretamente, como frameworks, APIs ou ferramentas de suporte. Elas podem ser gerenciadas automaticamente por ferramentas como Maven, que baixam, atualizam e integram essas dependências ao projeto conforme especificado na configuração do build.

[!IMPORTANT] Adicione as dependências de aplicação, desenvolvimento e teste no Spring Initializr ao criar o projeto. Para as de documentação, adicione manualmente no pom.xml, pois, neste caso, a dependência requisitada não está disponível no Spring Initializr.

2.1. De aplicação

Dependências de aplicação são bibliotecas necessárias para a execução do software em produção, como frameworks e APIs essenciais para as funcionalidades principais.

2.2. De desenvolvimento

Dependências de desenvolvimento são ferramentas e bibliotecas usadas apenas durante o desenvolvimento do projeto, como linters, geradores de código ou plugins de integração.

2.3. De teste

Dependências de teste são bibliotecas usadas para escrever e executar testes automatizados, como frameworks de testes unitários, mocks ou ferramentas de cobertura de código.

2.4. De documentação

Dependências de documentação são ferramentas utilizadas para gerar, gerenciar e publicar a documentação do projeto, como geradores de documentação a partir de comentários no código ou ferramentas de formatação de documentos.

3. Configurações

Estas configurações definem a conexão com o banco de dados MySQL, as credenciais de acesso e as propriedades do JPA para o projeto Movepass. Incluem parâmetros essenciais para garantir a persistência dos dados e o comportamento adequado da aplicação durante a execução. Insira esses valores no arquivo application.properties:

spring.jpa.open-in-view=false
springdoc.swagger-ui.path=/docs
spring.datasource.username=root
spring.datasource.password=12345678
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/movepass?createDatabaseIfNotExist=true

4. Entidades

As entidades do projeto Movepass representam os principais elementos do sistema, como Empresa, Funcionário, Academia e Assinatura. Abaixo está uma representação das classes dessas entidades:

classDiagram

class Academia {
  -Long id
  -String nome
  -String endereco
  -Boolean ativo
  +Academia()
  +getters()
  +setters()
}

class Assinatura {
  -Long id
  -LocalDate dataInicio
  -LocalDate dataTermino
  -Academia academia
  -Funcionario funcionario
  +Assinatura()
  +getters()
  +setters()
}

class Empresa {
  -Long id
  -String cnpj
  -String nome
  -Boolean ativo
  -List< Funcionario > funcionarios
  +Empresa()
  +getters()
  +setters()
}

class Funcionario {
  -Long id
  -String nome
  -String email
  -LocalDate dataContratacao
  -Boolean ativo
  +Funcionario()
  +getters()
  +setters()
}

5. Requisitos

Requisitos que devem ser seguidos ao implementar o exercício:

  1. Certifique-se de que a lógica de soft delete seja implementada de forma consistente, filtrando registros inativos em qualquer consulta. Soft delete consiste na exclusão lógica de registros no banco de dados. Em vez de remover os registros fisicamente, um campo booleano (neste caso o campo ativo) será utilizado para indicar se o registro está ativo ou inativo.

  2. As respostas da API podem utilizar as próprias entidades, embora seja recomendado usar DTOs de saída. Para as entradas, deve-se usar DTOs de entrada, solicitando apenas os dados necessários do cliente da aplicação.

  3. Utilize anotações para melhorar a visualização da documentação no Swagger UI, como:

    • Anotar o classe controladora com @Tag(name = "Nome do grupo de endpoints", description = "Descrição do grupo de endpoints") (io.swagger.v3.oas.annotations.tags.Tag);
    • Anotar cada método da classe controladora com @Operation(summary = "Resumo da operação", description = "Descrição detalhada da operação") (io.swagger.v3.oas.annotations.Operation).
  4. Lance exceções personalizadas quando necessário e capture-as na camada de controle usando um método anotado com @ExceptionHandler(ClasseException.class) (org.springframework.web.bind.annotation.ExceptionHandler).

  5. Padronize todas as respostas das classes controladoras usando ResponseEntity<Classe> (org.springframework.http.ResponseEntity). Lembre-se de usar os códigos de status corretamente para cada método (vide MOZILLA, Códigos de status de respostas HTTP). Para facilitar, faça uso do enum HttpStatus (org.springframework.http.HttpStatus).

6. Estrutura do projeto

A estrutura principal do projeto Movepass segue uma organização modular, separando as responsabilidades de cada camada do sistema. Isso facilita a manutenção e a escalabilidade do código. Abaixo está a estrutura sugerida:

src/main/java/com/movepass
├─── controller
│    ├─── AcademiaController.java
│    ├─── AssinaturaController.java
│    ├─── EmpresaController.java
│    └─── FuncionarioController.java
├─── dto
│    ├─── AcademiaDTO.java
│    ├─── AssinaturaDTO.java
│    ├─── EmpresaDTO.java
│    └─── FuncionarioDTO.java
├─── exception
│    └─── RegistroInexistenteException.java
├─── model
│    ├─── entity
│    │    ├─── Academia.java
│    │    ├─── Assinatura.java
│    │    ├─── Empresa.java
│    │    └─── Funcionario.java
│    └─── repository
│         ├─── AcademiaRepository.java
│         ├─── AssinaturaRepository.java
│         ├─── EmpresaRepository.java
│         └─── FuncionarioRepository.java
├─── service
│    ├─── AcademiaService.java
│    ├─── AssinaturaService.java
│    ├─── EmpresaService.java
│    └─── FuncionarioService.java
└─── MovepassApplication.java

7. Validações

Utilize Jakarta Constraints para validar os dados recebidos do cliente. Por exemplo:

[!TIP]

As anotações para validação podem ser encontradas no arquivo jakarta.validation.constraints.md.

[!WARNING]

Não esqueça de usar a anotação @Valid (jakarta.validation.Valid) nos parâmetros das controllers para que as validações funcionem corretamente.

8. Endpoints

Crie endpoints para realizar as operações básicas de CRUD (Create, Read, Update, Delete) para cada entidade. Cada endpoint deve seguir o padrão RESTful, utilizando os métodos HTTP adequados:

9. Testes

Para garantir a qualidade do código e o funcionamento correto da aplicação, realizaremos testes unitários. Utilizaremos a biblioteca Spring Boot Starter Test, que já vem incluída por padrão quando geramos um projeto no Spring Initializr, para realizar esses testes unitários e assegurar que cada componente do sistema esteja funcionando como esperado.

[!NOTE]

Testes unitários x Testes de integração

Testes Unitários: Focam em testar componentes individuais de um sistema (como métodos ou funções) de forma isolada, garantindo que cada parte funcione corretamente por si só. O objetivo é verificar a lógica interna de uma unidade de código sem depender de outros módulos ou partes do sistema. Usam mocks para substituir dependências externas.

Testes de Integração: Avaliam a interação entre múltiplos componentes ou módulos do sistema. O foco é garantir que diferentes partes (como camadas de serviço, repositórios etc.) funcionem corretamente juntas. Esses testes verificam se a comunicação e integração entre essas partes ocorrem conforme o esperado.

9.1. Estrutura de diretórios

Para manter a organização, a estrutura de diretórios de testes deve espelhar a estrutura usada em src/main. Ou seja, cada classe em src/main terá uma classe de teste correspondente em src/test. As classes de teste devem ter o sufixo Test por convenção. Exemplo:

9.2. Configurações

Cada classe de teste deve ser anotada com @SpringBootTest (org.springframework.boot.test.context.SpringBootTest). Isso indica que o contexto do Spring será carregado durante a execução dos testes. Além disso, cada método de teste deve ser anotado com @Test (org.junit.jupiter.api.Test):

@SpringBootTest
public class ClasseComTestes {

    @Test
    public void metodoTeste1() {
    }

    @Test
    public void metodoTeste2() {
    }
}

9.3. Mocks

Mocks simulam o comportamento de objetos reais, permitindo focar no comportamento da unidade sob teste. Usamos a biblioteca Mockito para criar mocks. A anotação @MockBean substitui um bean no contexto do Spring por um mock durante os testes.

Exemplo: Testando um serviço de e-mail

Vamos considerar um cenário em que temos um serviço de notificação (ServicoDeNotificacao) que utiliza um componente externo (EnviadorDeEmail) para enviar e-mails. Queremos testar apenas o comportamento do ServicoDeNotificacao sem depender da implementação real de envio de e-mails.

// Classe a ser testada

@Service
public class ServicoDeNotificacao {

    @Autowired
    private final EnviadorDeEmail enviadorDeEmail;

    public boolean enviarEmailDeBoasVindas(String enderecoEmail) {
        String mensagem = "Bem-vindo à nossa plataforma!";
        return enviadorDeEmail.enviarEmail(enderecoEmail, mensagem);
    }
}
// Teste unitário com Mock

@SpringBootTest
public class ServicoDeNotificacaoTest {

    @Autowired
    private ServicoDeNotificacao servicoDeNotificacao;

    @MockBean
    private EnviadorDeEmail enviadorDeEmail;

    @Test
    public void deveEnviarEmailDeBoasVindas() {
        Mockito.when(enviadorDeEmail.enviarEmail("usuario@exemplo.com", "Bem-vindo à nossa plataforma!"))
               .thenReturn(true);

        boolean resultado = servicoDeNotificacao.enviarEmailDeBoasVindas("usuario@exemplo.com");

        Assertions.assertTrue(resultado);

        Mockito.verify(enviadorDeEmail, Mockito.times(1))
               .enviarEmail("usuario@exemplo.com", "Bem-vindo à nossa plataforma!");
    }
}

Neste exemplo:

10. Conclusão

Ao concluir o desenvolvimento do projeto Movepass, você terá criado uma API REST funcional para a gestão de academias e assinaturas utilizando Java e Spring Boot. Este exercício proporcionou uma valiosa oportunidade para aplicar conceitos essenciais de Programação Orientada a Objetos (POO), implementar testes unitários e seguir boas práticas de desenvolvimento de software, consolidando assim suas habilidades técnicas e aprimorando sua experiência no desenvolvimento de APIs.

Voltar