JUnit 4 comparar conjuntos


102

Como você afirmaria sucintamente a igualdade dos Collectionelementos, especificamente a Setna JUnit 4?



Você está tentando afirmar que dois conjuntos são iguais entre si (contêm os mesmos elementos) ou que dois elementos do mesmo conjunto são iguais?
Bill the Lizard

Preciso ver se os elementos de dois conjuntos são iguais
Eqbal

Respostas:


103

Você pode afirmar que os dois Sets são iguais um ao outro, o que invoca o Set equals()método .

public class SimpleTest {

    private Set<String> setA;
    private Set<String> setB;

    @Before
    public void setUp() {
        setA = new HashSet<String>();
        setA.add("Testing...");
        setB = new HashSet<String>();
        setB.add("Testing...");
    }

    @Test
    public void testEqualSets() {
        assertEquals( setA, setB );
    }
}

Isso @Testpassará se os dois Sets tiverem o mesmo tamanho e contiverem os mesmos elementos.


7
Isso não exibe resultados muito bons no relatório. Se seus toStrings estiverem claramente definidos, é melhor, mas ainda não é bom (uma pequena diferença pode resultar em uma página de texto)
Bill K,

Uhm, como posso obter: java.lang.AssertionError: esperado: java.util.Hashtable <{CompanyName = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, = AvrIfd, QuoteId = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Categoria = AvrIfd, QuoteId = 434274020498 Nome_da_compresa.utilizadocto. 9: mas 218268 = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Category = AvrIfd, QuoteId = 4342740204922826921}>
Giovanni Botta

3
@Giodude Você tem equalse hashCodeimplementou na classe que está armazenando em seu Hashtable?
Bill the Lizard,

Como você pode ver, são apenas strings e um longo ... Estou testando o Avro para serializar e desserializar um mapa e esse é o resultado. Acho que deve haver algo estranho com a maneira como as strings são serializadas e desserializadas que faz com que o teste falhe, mas não consigo encontrar o problema.
Giovanni Botta

Não funcionou para mim, embora eu esteja comparando dois HashSet <Long>. A resposta @MattFriedman realmente funciona para meu caso de uso.
bluecollarcoder

46

Apache commons para o resgate novamente.

assertTrue(CollectionUtils.isEqualCollection(coll1, coll2));

Funciona como um encanto. Não sei por que, mas descobri que com coleções o seguinte assertEquals(coll1, coll2)nem sempre funciona. No caso em que falhou para mim, eu tinha duas coleções apoiadas por Sets. Nem hamcrest nem junit diriam que as coleções eram iguais, embora eu tivesse certeza de que eram. Usando CollectionUtils funciona perfeitamente.


20
Na verdade, isso é trivial, a parte complicada é indicar claramente a diferença para quem ligou
Bill K,

1
A resposta aceita é uma boa resposta para a pergunta original (teste de unidade especificamente para dois Conjuntos), mas essa resposta com CollectionUtils é, creio, uma resposta melhor para o caso mais geral. Não consegui comparar uma coleção e um conjunto a menos que use CollectionUtils.
Jay

16

com hamcrest :

assertThat(s1, is(s2));

com afirmação simples:

assertEquals(s1, s2);

NB: t o método equals () da classe de conjunto concreto é usado


1
Prefiro esse método, pois o Hamcrest vem com o JUnit 4, portanto, não há necessidade de outras bibliotecas.
JRSofty

2
Isso pode não funcionar quando os conjuntos têm tipos diferentes.
Hans-Peter Störr

7

Um caso particularmente interessante é quando você compara

   java.util.Arrays$ArrayList<[[name,value,type], [name1,value1,type1]]> 

e

   java.util.Collections$UnmodifiableCollection<[[name,value,type], [name1,value1,type1]]>

Até agora, a única solução que vejo é transformar os dois em conjuntos

assertEquals(new HashSet<CustomAttribute>(customAttributes), new HashSet<CustomAttribute>(result.getCustomAttributes()));

Ou eu poderia compará-los elemento por elemento.


Na verdade, existem várias soluções para isso apresentadas nas demais respostas. Os conjuntos são um pouco infelizes para isso, de qualquer maneira, já que ignoram a ordem. Talvez ArrayList?
Hans-Peter Störr

4

Como um método adicional baseado em array ... você pode considerar o uso de asserções de array não ordenadas em junitx. Embora o exemplo do Apache CollectionUtils funcione, também há uma série de extensões de asserção sólidas:

Eu acho que o

ArrayAssert.assertEquivalenceArrays(new Integer[]{1,2,3}, new Integer[]{1,3,2});

A abordagem será muito mais legível e depurável para você (todas as Coleções suportam toArray (), portanto, deve ser fácil o suficiente para usar os métodos ArrayAssert.

Claro que a desvantagem aqui é que, junitx é um arquivo jar adicional ou uma entrada maven ...

 <dependency org="junit-addons" name="junit-addons" rev="1.4"/>

2

Verifique este artigo . Um exemplo disso:

@Test  
public void listEquality() {  
    List<Integer> expected = new ArrayList<Integer>();  
    expected.add(5);  

    List<Integer> actual = new ArrayList<Integer>();  
    actual.add(5);  

    assertEquals(expected, actual);  
}  

Link curto, mas ótimo, explica muito rápido o que você pode fazer com Junit4-
Johannes

1
O link está quebrado. Alguma chance de você encontrar uma versão arquivada online ou resumir seu conteúdo?
pzp de

1

Usando Hamcrest:

assertThat( set1, both(everyItem(isIn(set2))).and(containsInAnyOrder(set1)));

Isso também funciona quando os conjuntos têm diferentes tipos de dados e relata a diferença em vez de apenas falhar.


2
Qual é a importação de isIn? O IntelliJ não pode resolver a importação com nenhum pacote Hamcret.
fabien

0

Se você deseja verificar se uma Lista ou Conjunto contém um conjunto de valores específicos (em vez de compará-lo com uma coleção já existente), muitas vezes o método toString de coleções é útil:

String[] actualResult = calltestedmethod();
assertEquals("[foo, bar]", Arrays.asList(actualResult).toString());

List otherResult = callothertestedmethod();
assertEquals("[42, mice]", otherResult.toString());

Isso é um pouco mais curto do que primeiro construir a coleção esperada e compará-la com a coleção real, e mais fácil de escrever e corrigir.

(Reconhecidamente, este não é um método particularmente limpo e não consegue distinguir um elemento "foo, bar" de dois elementos "foo" e "bar". Mas, na prática, acho que é mais importante que seja fácil e rápido escrever testes , caso contrário, muitos desenvolvedores simplesmente não o farão sem serem pressionados.)


Isso faz com que o resultado do seu teste de unidade dependa da implementação de toString da lista. Se eles decidirem alterar a formatação, o teste de unidade não funcionará mais. Eu não consideraria isso seguro.
Laurens Op 't Zandt

@ LaurensOp'tZandt Você quer dizer a Oracle mudando o formato de Collection.toList ()? Isso certamente não vai acontecer. Você está, entretanto, certo de que não é particularmente limpo. Mas, na prática, tenho a impressão de que o mais importante é que seja muito fácil escrever testes.
Hans-Peter Störr

Eu concordo, acho que o método toString provavelmente não mudará. Portanto, provavelmente continuará funcionando. Só queria salientar que não é uma forma muito limpa. Mas na verdade é muito fácil. Um problema que surge é ao comparar conjuntos. Uma vez que seu pedido não é garantido.
Laurens Op 't Zandt

0

Gosto da solução de Hans-Peter Störr ... Mas acho que não está totalmente correta. Infelizmente containsInAnyOrder, não aceita Collectionobjetos para comparar. Portanto, tem que ser um Collectionde Matchers:

assertThat(set1, containsInAnyOrder(set2.stream().map(IsEqual::equalTo).collect(toList())))

As importações são:

import static java.util.stream.Collectors.toList;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertThat;
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.