🧪 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. 🏁