🧪 1.10 A próxima funcionalidade: Os 3 Maiores Lances

Nesta etapa, implementaremos uma regra de negócio mais complexa: o retorno dos três maiores lances do leilão. No Java 17, podemos realizar essa operação de forma elegante e expressiva utilizando a API de Streams.

🏗️ Implementação Moderna (Clean Code)

Em vez de ordenações manuais e sublistas frágeis, utilizamos fluidez funcional:

import java.util.*;
import static java.util.Comparator.comparingDouble;
 
public class Avaliador {
    private double maiorDeTodos = Double.NEGATIVE_INFINITY;
    private double menorDeTodos = Double.POSITIVE_INFINITY;
    private List<Lance> maiores;
 
    public void avalia(Leilao leilao) {
        leilao.getLances().forEach(lance -> {
            if (lance.getValor() > maiorDeTodos) maiorDeTodos = lance.getValor();
            if (lance.getValor() < menorDeTodos) menorDeTodos = lance.getValor();
        });
 
        pegaOsMaioresNo(leilao);
    }
 
    private void pegaOsMaioresNo(Leilao leilao) {
    // Ordenação decrescente e limite dos 3 primeiros usando Streams
    this.maiores = leilao.getLances().stream()
            .sorted(comparingDouble(Lance::getValor).reversed())
            .limit(3)
            .toList();
}
    public List<Lance> getTresMaiores() { return this.maiores; }
}

🧪 Testando com AssertJ

Ao testar coleções, o AssertJ brilha ao permitir verificar o tamanho e o conteúdo em uma única corrente de chamadas:

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.extractProperty;
import org.junit.jupiter.api.Test;
 
class AvaliadorTest {
 
    @Test
    void deveEncontrarOsTresMaioresLances() {
        var joao = new Usuario("João");
        var maria = new Usuario("Maria");
        var leilao = new Leilao("Console Next Gen");
 
        leilao.propoe(new Lance(joao, 100.0));
        leilao.propoe(new Lance(maria, 200.0));
        leilao.propoe(new Lance(joao, 300.0));
        leilao.propoe(new Lance(maria, 400.0));
 
        var leiloeiro = new Avaliador();
        leiloeiro.avalia(leilao);
 
        var maiores = leiloeiro.getTresMaiores();
 
        // Validação de Elite: Tamanho e Ordem dos Valores
        assertThat(maiores).hasSize(3)
                .extracting(Lance::getValor)
                .containsExactly(400.0, 300.0, 200.0);
    }
}

Testes de Regressão 🛡️

Ao implementar os “Top 3”, garantimos que os testes de “Maior” e “Menor” continuem passando. Se uma nova funcionalidade quebrar uma antiga, o JUnit nos avisará instantaneamente. 🚀


🧠 Um único assert por teste?

A regra de ouro na Engenharia de Elite é: Um conceito por teste. Se um comportamento afeta o estado interno de um objeto (como maior, menor e lista de maiores), é aceitável verificar todos esses pontos, pois eles compõem a unidade lógica daquela avaliação. 🏁


⬅️ Capítulo Anterior | Próximo Capítulo ➡️