Pular para o conteúdo principal

Criando endpoints pensando em TDD - desenvolvimento de softwares guiado por Testes

 TDD é a sigla para Test Driven Development, que em português significa Desenvolvimento Orientado por Testes. Esse é um método de desenvolvimento muito comum atualmente. Ele se baseia na aplicação de pequenos ciclos de repetições. Em cada um deles, um teste é aplicado.

Basicamente é o que o nome diz, o desenvolvimento de softwares guiado por Testes. Vale dizer que isso começou com o Kent Beck, que foi o criador do TDD.

Fiz esse desenho para ilustrar melhor sobre:





E a ideia é exatamente essa mesmo, você escrever primeiro o teste unitário no seu código fonte, antes mesmo de escrever a funcionalidade em si. Ou seja:

1- Escreva um teste que vai falhar (exatamente porque a funcionalidade ainda nem existe).

2- Escreva a funcionalidade em si, com o código que vai fazê-la funcionar

3- Refatore o seu código, eliminando redundâncias, deixando ele mais elegante e etc…


Hands on

Chega de resumir e vamos colocar a mão na massa. Bom, vou criar um endpoint simples com Spring que o único objetivo é retornar uma lista e outro método em uma service que o objetivo é saber se uma idade que será passada como parâmetro é maior de idade ou não.

Vamos ao nosso primeiro endpoint, lembrando que primeiro vamos criar uma classe chamada Usuário, ela ainda não faz parte da nossa funcionalidade em si, mas será uma classe importante:


import lombok.Builder;

import lombok.Data;

@Data

@Builder

public class Usuario {

    private String nome;

    private String email;

    private int idade;

}


Vamos adicionar ao nosso projeto essas duas dependências:

<!--junit-->

<dependency>

               <groupId>junit</groupId>

                                            <artifactId>junit</artifactId>

                              </dependency>

                              <!--mockito-->

                              <dependency>

                                            <groupId>org.mockito</groupId>

                                            <artifactId>mockito-core</artifactId>

</dependency>


Feito isso, vamos criar a nossa UsuarioController da seguinte forma:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;

@RestController
@RequestMapping("usuario")
public class UsuarioController {
       
}

Repare que ela está vazia, sem implementação alguma e de fato essa é a ideia!

Agora vamos criar o teste da nossa controller:


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.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

@WebMvcTest(UsuarioController.class)
public class UsuarioControllerTests {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testarListaUsuario() throws Exception {
        this.mockMvc.perform(MockMvcRequestBuilders.get("/usuario")) //teste para acessar o endpoint
                .andDo(MockMvcResultHandlers.print()) // print do resultado do teste
                .andExpect(MockMvcResultMatchers.jsonPath("$").isArray()); // verificando se o endpoint retorna um array
    }

Repare que nós já escrevemos o teste do que o nosso endpoint tem que fazer (retornar uma lista), porém ainda nem criamos a funcionalidade em si, por isso quando rodamos o teste, vai dar erro mesmo:






Perfeito! Agora que já sabemos o que o nosso endpoint tem que fazer e inclusive testamos isso, vamos criar de fato a funcionalidade:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@RestController
@RequestMapping("usuario")
public class UsuarioController {

    @GetMapping
    public List<Usuario> listaUsuario() {
        List<Usuario> listaUsuarios = new ArrayList<>();
        listaUsuarios.add(new Usuario("Nataniel", "nataniel.paiva@gmail.com", 29));
        return listaUsuarios;
    }

}

Esse é o passo 2, como a funcionalidade está criada, agora podemos rodar de fato o teste trazendo um resultado correto:

Agora, vamos ao passo 3, que é o de refatorar o código do nosso endpoint:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@RestController
@RequestMapping("usuario")
public class UsuarioController {

    @GetMapping
    public List<Usuario> listaUsuario() {
        return Arrays.asList(
                Usuario
                .builder()
                .nome("Nataniel")
                .email("nataniel.paiva@gmail.com")
                .idade(29).build());
    }

}

Agora no passo 3 podemos deixar o nosso código mais elegante! E a ideia do TDD é exatamente essa, você vai construindo as suas funcionalidades guiado pelos testes.

Agora vamos para a nossa segunda funcionalidade. Vamos precisar de uma Service com um método para validar se uma idade passada como parâmetro é maior de idade ou não.

Criamos apenas a “casca” da nossa service:

import org.springframework.stereotype.Service;

@Service
public class UsuarioService {
  
  public boolean verificaMaiorIdade(int idade){
        return true;
    }

}

Até criei o método, mas repare que ele apenas tem o retorno para não ter erro de compilação. Agora vamos para o nosso teste:

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class UsuarioServiceTests {

    @InjectMocks
    public UsuarioService usuarioService;

    @Test
    public void verificaMaiorIdade() {
        Boolean teste = usuarioService.verificaMaiorIdade(18);
        Assert.assertTrue(teste);
    }

    @Test
    public void verificaMenorIdade() {
        boolean teste = usuarioService.verificaMaiorIdade(17);
        Assert.assertFalse(teste);
    }

}

Repare que um dos testes escritos vai trazer um falso positivo, porém estamos testando o que queremos de fato na funcionalidade. Então vamos criar a funcionalidade de fato.

import org.springframework.stereotype.Service;

@Service
public class UsuarioService {

    public boolean verificaMaiorIdade(int idade){
        boolean retorno = false;
        if(idade >= 18){
            retorno = true;
        }
        return retorno;
    }

}

Repare que agora os dois testes que fizemos irão passar. Agora vamos tentar melhorar o nosso código:

import org.springframework.stereotype.Service;

@Service
public class UsuarioService {

    public boolean verificaMaiorIdade(int idade){
        return idade >= 18;
    }

}





Comentários

Postagens mais visitadas deste blog

VISÃO GLOBAL - sobre IDoc O IDoc é um objeto SAP que transporta dados de uma transação comercial de um sistema para outro na forma de mensagem eletrônica.  IDoc é um acrônimo para  I  ntermediate  Doc  ument.  O objetivo de um IDoc é transferir dados ou informações do SAP para outros sistemas e vice-versa.  A transferência do SAP para o sistema não SAP é feita via subsistemas EDI (Electronic Data Interchange), enquanto para a transferência entre dois sistemas SAP, o ALE é usado. O IDoc pode ser acionado no sistema SAP ou no subsistema EDI. Isso depende da direção na qual o IDoc é enviado e é chamado como IDoc de entrada e IDoc de saída de acordo.  No caso de fluxo de saída, o IDoc é acionado no SAP por meio do controle de mensagens do documento, que é então enviado ao subsistema EDI. EDI converte os dados do IDoc em XML ou formato equivalente e, em seguida, envia os dados para o sistema parceiro através da Internet. Para o fluxo de entrad...

Saída de mercadorias (MIGO_GI)

Saída Logística - Administração de Materiais - Administração de Estoques - Movimento mercadoria (MIGO) - Saída de mercadorias (MIGO_GI) - Saída de mercadorias (MB1A) Uma saída de mercadoria (SM) é a retirada de material do estoque, seja para consumo ou expedição para um cliente. Tipo de movimento - 201 – Consumo de mercadoria para centro de custos vindo do depósito - 221 – Consumo de mercadoria para projeto vindo do depósito - 261 – Consumo para ordem vindo do depósito - 281 – Consumo para diagrama de rede vindo do depósito - 541 – Subcontratação: remessa dos componentes de livre utilizável para fornecedor - 551 – Retirada para sucata de livre utilizável As opções da transação MIGO_GI são: Saída e Estorno. Campos a serem preenchidos para Saída de Mercadoria: - Selecionar “Saída de mercadorias” - Entrar com os dados dos itens a serem retirados do depósito: o Material o Quantidade o Centro o Depósito o Centro de Custo (obrigatório dependendo do tipo de saída) Campos...

Veja como solucionar o erro 'Não permite retransmissão' em iPhones, iPads e iPods

Você tentou enviar e-mails do seu UOL Mail por um iPhone, iPad ou iPod, mas recebeu a mensagem  O destinatário foi rejeitado pelo servidor porque ele não permite retransmissão ? Isso indica que existe algum erro na configuração do SMTP. Essa configuração junto com a configuração IMAP são os responsáveis por receber e enviar e-mails usando o gerenciador de contas dos aparelhos da Apple.  Clique aqui e verifique o passo a passo ilustrado para fazer essas configurações .  Se você já configurou seu aparelho, mas o erro persiste, é necessário verificar alguns dados.  Um erro comum, por exemplo, é esquecer de corrigir o campo  Nome do Host  que contém o link SMTP. É necessário colocar a letra "s" após o smtp, ficando:  smtps.uol.com.br . Vá em  Ajuste s, selecione  Mail, Contatos, Calendário . Selecione a conta do UOL que você configurou e clique em  Conta . Verifique se o Servidor de Correio de Saída está com o link  smtps.uol...