2
respostas

[Sugestão] Validação da classe ValidacaoTutorComLimiteDeAdocoes antes da otimização do código

Assim como a classe ValidacaoTutorComAdocaoEmAndamento, a classe ValidacaoTutorComLimiteDeAdocoes apresenta um código diferente do código testado na primeira resolução dos desafios. O código presente no projeto para download está desta forma:

@Component
public class ValidacaoTutorComLimiteDeAdocoes implements ValidacaoSolicitacaoAdocao {

    @Autowired
    private AdocaoRepository adocaoRepository;

    @Autowired
    private TutorRepository tutorRepository;

    public void validar(SolicitacaoAdocaoDto dto) {
        List<Adocao> adocoes = adocaoRepository.findAll();
        Tutor tutor = tutorRepository.getReferenceById(dto.idTutor());
        for (Adocao a : adocoes) {
            int contador = 0;
            if (a.getTutor() == tutor && a.getStatus() == StatusAdocao.APROVADO) {
                contador = contador + 1;
            }
            if (contador == 5) {
                throw new ValidacaoException("Tutor chegou ao limite máximo de 5 adoções!");
            }
        }
    }

}

De inicio podemos reparar em uma correção necessária para que a validação funcione, sendo ela remover a iniciação da variável contador de dentro do laço for e adiciona-la antes do inicio do mesmo, caso contrário ela será sempre zerada para cada elemento percorrido na lista e sua incrementação não passará de 1:

@Component
public class ValidacaoTutorComLimiteDeAdocoes implements ValidacaoSolicitacaoAdocao {

    @Autowired
    private AdocaoRepository adocaoRepository;

    @Autowired
    private TutorRepository tutorRepository;

    public void validar(SolicitacaoAdocaoDto dto) {
        List<Adocao> adocoes = adocaoRepository.findAll();
        Tutor tutor = tutorRepository.getReferenceById(dto.idTutor());
        int contador = 0;
        for (Adocao a : adocoes) {
            if (a.getTutor() == tutor && a.getStatus() == StatusAdocao.APROVADO) {
                contador = contador + 1;
            }
            if (contador == 5) {
                throw new ValidacaoException("Tutor chegou ao limite máximo de 5 adoções!");
            }
        }
    }

}

Por fim, os testes desenvolvidos para cobrir os casos possíveis dessa classe de validação foram implementados da seguinte maneira:

@ExtendWith(MockitoExtension.class)
class ValidacaoTutorComLimiteDeAdocoesTest {

    @InjectMocks
    private ValidacaoTutorComLimiteDeAdocoes validacaoTutorComLimiteDeAdocoes;
    @Mock
    private AdocaoRepository adocaoRepository;
    @Mock
    private TutorRepository tutorRepository;
    @Mock
    private SolicitacaoAdocaoDto dto;
    @Mock
    private Tutor tutor;
    @Mock
    private Pet pet;
    @Spy
    private List<Adocao> listaDeAdocoes = new ArrayList<>();
    @Spy
    private Adocao adocao;


    @Test
    void deveriaPermitirAdocaoPorTutorComLimite() {

        adocao = new Adocao(tutor, pet, "Motivo qualquer");
        adocao.marcarComoAprovada();
        listaDeAdocoes.add(adocao);
        BDDMockito.given(adocaoRepository.findAll()).willReturn(listaDeAdocoes);
        BDDMockito.given(tutorRepository.getReferenceById(dto.idTutor())).willReturn(tutor);

        Assertions.assertDoesNotThrow(() -> validacaoTutorComLimiteDeAdocoes.validar(dto));
    }

    @Test
    void deveriaNaoPermitirAdocaoPorTutorSemLimite() {

        adocao = new Adocao(tutor, pet, "Motivo qualquer");
        adocao.marcarComoAprovada();
        for(int i = 0; i < 5; i++)
            listaDeAdocoes.add(adocao);

        BDDMockito.given(adocaoRepository.findAll()).willReturn(listaDeAdocoes);
        BDDMockito.given(tutorRepository.getReferenceById(dto.idTutor())).willReturn(tutor);

        Assertions.assertThrows(ValidacaoException.class, () -> validacaoTutorComLimiteDeAdocoes.validar(dto));
    }

}

Gostaria de um feedback sobre minha implementação dos testes e também disponibilizar o código para os demais alunos com dificuldade nessa etapa.

2 respostas

Olá, Jonas! Como vai? Espero que bem?

Primeiramente, parabéns pela sua iniciativa em compartilhar a sua implementação e buscar feedback. Isso é muito importante para o seu aprendizado e também para ajudar outros estudantes!

Vamos à sua dúvida:

Sua implementação da classe ValidacaoTutorComLimiteDeAdocoes parece correta. Você identificou corretamente o problema com a inicialização da variável contador dentro do loop e fez a correção necessária. Isso é fundamental para garantir que o contador seja incrementado corretamente para cada adoção aprovada do tutor.

Quanto aos seus testes na classe ValidacaoTutorComLimiteDeAdocoesTest, eles também parecem bem implementados. Você cobriu os dois cenários principais:

  1. O cenário em que o tutor ainda não atingiu o limite de adoções, onde você não espera que uma exceção seja lançada.
  2. O cenário em que o tutor já atingiu o limite de adoções, onde você espera que a exceção ValidacaoException seja lançada.

Uma sugestão seria adicionar mais alguns testes para cobrir outros cenários possíveis, como, por exemplo, quando a lista de adoções está vazia, ou quando o tutor não tem nenhuma adoção aprovada. Isso ajudaria a tornar seus testes ainda mais robustos.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.

Também notei que o código apresentado no vídeo está completamente diferente do código disponível para download (inclusive considero que o código disponível para download funciona melhor como exercício do que o código apresentado no vídeo). Minha solução:

    @Test
    void deveriaRetornarExcecaoDeValidacao() {
        
        BDDMockito.given(adocaoRepository.findAll()).willReturn(adocoes);
        BDDMockito.given(tutorRepository.getReferenceById(dto.idTutor())).willReturn(tutor);
        
        do {
            adocoes.add(adocao);
        } while (adocoes.size() < 5);
        
        BDDMockito.given(adocao.getTutor()).willReturn(tutor);
        BDDMockito.given(adocao.getStatus()).willReturn(StatusAdocao.APROVADO);
        
        Assertions.assertThrows(ValidacaoException.class, ()-> validacao.validar(dto));
        
    }
    
    @Test
    void naoDeveriaRetornarExcecaoDeValidacao() {
        
        BDDMockito.given(adocaoRepository.findAll()).willReturn(adocoes);
        BDDMockito.given(tutorRepository.getReferenceById(dto.idTutor())).willReturn(tutor);
        
        adocoes.add(adocao);
        
        BDDMockito.given(adocao.getTutor()).willReturn(tutor2);
        
        Assertions.assertDoesNotThrow(()-> validacao.validar(dto));
        
    }

}

As maiores diferenças em relação à sua solução foi o uso do "do while" ao invés do for() e o fato de eu ter usado duas intÂncias mockadas de tutor.