Fiz uma implementação um pouco diferente, visando evitar duplicação de código. Gostaria que vcs opinassem.
package br.com.caelum.leilao.servico;
import static org.hamcrest.Matchers.closeTo;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import br.com.caelum.leilao.dominio.Leilao;
import br.com.caelum.leilao.dominio.LeilaoDataBuilder;
import br.com.caelum.leilao.dominio.LeilaoDataBuilder.Ordem;
public class AvaliadorTest {
@Test
public void deveAcharValoresEmOrdemCrescenteDeLances(){
Avaliador avaliador = criarAvaliadorcomLeilaoTendoLancesEmOrdem(5, Ordem.CRESCENTE);
assertThat(avaliador.getMaiorLance(), closeTo(5, 0.0001));
assertThat(avaliador.getMenorLance(), closeTo(1, 0.0001));
assertThat(avaliador.getLanceMedio(), closeTo(3, 0.0001));
}
@Test
public void deveAcharValoresEmOrdemDecrescenteDeLances(){
Avaliador avaliador = criarAvaliadorcomLeilaoTendoLancesEmOrdem(5, Ordem.DECRESCENTE);
assertThat(avaliador.getMaiorLance(), closeTo(999_999, 0.0001));
assertThat(avaliador.getMenorLance(), closeTo(999_995, 0.0001));
assertThat(avaliador.getLanceMedio(), closeTo(999_997, 0.0001));
}
@Test
public void deveAcharValoresComUnicoLance(){
Avaliador avaliador = criarAvaliadorcomLeilaoTendoLancesEmOrdem(1, Ordem.CRESCENTE);
assertThat(avaliador.getMaiorLance(), closeTo(1, 0.0001));
assertThat(avaliador.getMenorLance(), closeTo(1, 0.0001));
assertThat(avaliador.getLanceMedio(), closeTo(1, 0.0001));
}
private Avaliador criarAvaliadorcomLeilaoTendoLancesEmOrdem(int lances, Ordem ordem) {
Avaliador avaliador = new Avaliador();
Leilao leilao = LeilaoDataBuilder.builder()
.comNumeroLancesIgualA(lances)
.na(ordem)
.build();
avaliador.avaliar(leilao);
return avaliador;
}
}
package br.com.caelum.leilao.dominio;
import java.util.stream.IntStream;
public class LeilaoDataBuilder {
private String nomeLeilao = "Playstation 4";
private Ordem ordem = Ordem.CRESCENTE;
private int numeroLances = 3;
public LeilaoDataBuilder com(String nome){
this.nomeLeilao = nome;
return this;
}
public LeilaoDataBuilder na(Ordem ordem){
this.ordem = ordem;
return this;
}
public LeilaoDataBuilder comNumeroLancesIgualA(int numeroLances){
this.numeroLances = numeroLances;
return this;
}
public static LeilaoDataBuilder builder(){
return new LeilaoDataBuilder();
}
public Leilao build() {
Leilao leilao = new Leilao(nomeLeilao);
IntStream.range(0, numeroLances)
.mapToObj(i -> new Lance(new Usuario("Fulano " + i), ordem.proximoNumero(i)))
.forEach(l -> leilao.propoe(l));
return leilao;
}
public enum Ordem{
CRESCENTE(1,1), DECRESCENTE(999_999, -1);
private int numeroBase;
private int numeroSinal;
private Ordem(int numeroBase, int numeroSinal) {
this.numeroBase = numeroBase;
this.numeroSinal = numeroSinal;
}
public int proximoNumero(int numeroIteracao) {
return numeroBase + (numeroIteracao * numeroSinal);
}
}
}
package br.com.caelum.leilao.dominio;
import java.util.Objects;
public class Lance implements Comparable<Lance> {
private double valor;
private Usuario usuario;
public Lance(Usuario usuario, double valor) {
this.usuario = usuario;
this.valor = valor;
}
public Usuario getUsuario() {
return usuario;
}
public double getValor() {
return valor;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(valor);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Lance other = (Lance) obj;
if (Double.doubleToLongBits(valor) != Double.doubleToLongBits(other.valor))
return false;
return true;
}
@Override
public int compareTo(Lance outroLance) {
Objects.requireNonNull(outroLance);
return (int) Math.signum(valor - outroLance.getValor());
}
@Override
public String toString() {
return String.format("Lance [valor=%s, usuario=%s]", valor, usuario);
}
}
package br.com.caelum.leilao.dominio;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import com.google.common.collect.Lists;
public class Leilao {
private String descricao;
private List<Lance> lances;
public Leilao(String descricao) {
this.descricao = descricao;
this.lances = Lists.newArrayList();
}
public void propoe(Lance lance) {
lances.add(lance);
Collections.sort(lances);
}
public String getDescricao() {
return descricao;
}
public List<Lance> getTresMaioresLances() {
int indiceMinimoTresMaioresLances = lances.size() - 3 >= 0 ? lances.size() - 3 : lances.size() - 1;
List<Lance> tresMaioresLances = lances.subList(indiceMinimoTresMaioresLances,lances.size());
Collections.sort(tresMaioresLances, Comparator.comparingDouble(Lance::getValor).reversed());
return tresMaioresLances;
}
public List<Lance> getLances() {
return lances;
}
@Override
public String toString() {
return String.format("Leilao [descricao=%s, lances=%s]", descricao, lances);
}
}