Afirme sobre uma lista no Junit

Como fazer asserções sobre uma lista em um caso de teste JUnit ? Não apenas o tamanho da lista, mas também o conteúdo da lista.

Eu percebo que isso foi perguntado há alguns anos, provavelmente esse recurso não estava por aí. Mas agora é fácil fazer isso:

 @Test public void test_array_pass() { List actual = Arrays.asList("fee", "fi", "foe"); List expected = Arrays.asList("fee", "fi", "foe"); assertThat(actual, is(expected)); assertThat(actual, is(not(expected))); } 

Se você tiver uma versão recente do Junit instalada com o hamcrest, basta adicionar essas importações:

 import static org.junit.Assert.*; import static org.hamcrest.CoreMatchers.*; 

http://junit.org/junit4/javadoc/latest/org/junit/Assert.html#assertThat(T, org.hamcrest.Matcher)

http://junit.org/junit4/javadoc/latest/org/hamcrest/CoreMatchers.html

http://junit.org/junit4/javadoc/latest/org/hamcrest/core/Is.html

Esta é uma resposta legada, adequada para o JUnit 4.3 e abaixo. A versão moderna do JUnit inclui mensagens de falha legíveis incorporadas no método assertThat. Prefira outras respostas sobre essa questão, se possível.

 List a = resultFromTest(); List expected = Arrays.asList(new E(), new E(), ...); assertTrue("Expected 'a' and 'expected' to be equal."+ "\n 'a' = "+a+ "\n 'expected' = "+expected, expected.equals(a)); 

Para o registro, como @Paul mencionou em seu comentário a esta resposta, duas List s são iguais:

se e somente se o object especificado também for uma lista, as duas listas terão o mesmo tamanho e todos os pares de elementos correspondentes nas duas listas serão iguais. (Dois elementos e1 e e2 são iguais se (e1==null ? e2==null : e1.equals(e2)) .) Em outras palavras, duas listas são definidas para serem iguais se elas contiverem os mesmos elementos na mesma ordem. . Essa definição garante que o método equals funcione corretamente em diferentes implementações da interface List .

Veja os JavaDocs da interface List .

Não se transforme em string e compare. Isso não é bom para perfomance. No junit, dentro de Corematchers, há um matcher para este => hasItems

 List yourList = Arrays.asList(1,2,3,4) assertThat(yourList, CoreMatchers.hasItems(1,2,3,4,5)); 

Essa é a melhor maneira que conheço para verificar elementos em uma lista.

Se você não se importa com a ordem dos elementos, eu recomendo ListAssert.assertEquals em addons de junit.

Link: http://junit-addons.sourceforge.net/

Para usuários preguiçosos do Maven:

   junit-addons junit-addons 1.4 test  
 List figureTypes = new ArrayList( Arrays.asList( 1, 2 )); List figureTypes2 = new ArrayList( Arrays.asList( 1, 2)); assertTrue(figureTypes .equals(figureTypes2 )); 

Se você não quiser criar uma lista de matriz, você pode tentar isso também

 @Test public void test_array_pass() { List list = Arrays.asList("fee", "fi", "foe"); Strint listToString = list.toString(); Assert.assertTrue(listToString.contains("[fee, fi, foe]")); // passes } 

Não reinvente a roda!

Há uma biblioteca do Google Code que faz isso para você: Hamcrest

[Hamcrest] Fornece uma biblioteca de objects correspondentes (também conhecidos como restrições ou predicados), permitindo que as regras de ‘correspondência’ sejam definidas declarativamente, para serem usadas em outras estruturas. Cenários típicos incluem estruturas de teste, bibliotecas de simulação e regras de validação da interface do usuário.

Você pode usar assertEquals no junit.

 import org.junit.Assert; import org.junit.Test; @Test public void test_array_pass() { List actual = Arrays.asList("fee", "fi", "foe"); List expected = Arrays.asList("fee", "fi", "foe"); Assert.assertEquals(actual,expected); } 

Se a ordem dos elementos for diferente, ela retornará o erro.

Se você estiver afirmando uma lista de objects de modelo, deverá replace o método equals no modelo específico.

  @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj != null && obj instanceof ModelName) { ModelName other = (ModelName) obj; return this.getItem().equals(other.getItem()) ; } return false; } 

Eu não faço isso todas as respostas acima estão dando a solução exata para comparar duas listas de objects. A maioria das abordagens acima pode ser útil ao seguir apenas o limite de comparações – Comparação de tamanho – Comparação de referência

Mas se tivermos listas de objects de mesmo tamanho e dados diferentes no nível de objects, essa comparação não ajudará.

Acho que a abordagem a seguir funcionará perfeitamente com a substituição de equals e hashcode method no object definido pelo usuário.

Eu usei o Xstream lib para override equals e hashcode mas podemos sobrescrever equals e hashcode por lógicas / comparações vencidas também.

Aqui é o exemplo para sua referência

  import com.thoughtworks.xstream.XStream; import java.text.ParseException; import java.util.ArrayList; import java.util.List; class TestClass { private String name; private String id; public void setName(String value) { this.name = value; } public String getName() { return this.name; } public String getId() { return id; } public void setId(String id) { this.id = id; } /** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object o) { XStream xstream = new XStream(); String oxml = xstream.toXML(o); String myxml = xstream.toXML(this); return myxml.equals(oxml); } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { XStream xstream = new XStream(); String myxml = xstream.toXML(this); return myxml.hashCode(); } } public class XstreamCompareTest { public static void main(String[] args) throws ParseException { checkObjectEquals(); } private static void checkObjectEquals() { List testList1 = new ArrayList(); TestClass tObj1 = new TestClass(); tObj1.setId("test3"); tObj1.setName("testname3"); testList1.add(tObj1); TestClass tObj2 = new TestClass(); tObj2.setId("test2"); tObj2.setName("testname2"); testList1.add(tObj2); testList1.sort((TestClass t1, TestClass t2) -> t1.getId().compareTo(t2.getId())); List testList2 = new ArrayList(); TestClass tObj3 = new TestClass(); tObj3.setId("test3"); tObj3.setName("testname3"); testList2.add(tObj3); TestClass tObj4 = new TestClass(); tObj4.setId("test2"); tObj4.setName("testname2"); testList2.add(tObj4); testList2.sort((TestClass t1, TestClass t2) -> t1.getId().compareTo(t2.getId())); if (isNotMatch(testList1, testList2)) { System.out.println("The list are not matched"); } else { System.out.println("The list are matched"); } } private static boolean isNotMatch(List clist1, List clist2) { return clist1.size() != clist2.size() || !clist1.equals(clist2); } } 

A coisa mais importante é que você pode ignorar os campos por Anotação (@XStreamOmitField) se não quiser include campos na verificação igual de Objetos. Existem muitas Anotações como esta para configurar, então dê uma olhada nas annotations desta biblioteca.

Tenho certeza de que essa resposta economizará seu tempo para identificar a abordagem correta para comparar duas listas de objects :). Por favor, comente se você vir alguma questão sobre isso.

assertEquals(Object, Object) do JUnit4 / JUnit 5 ou assertThat(actual, is(expected)); de Hamcrest proposto nas outras respostas funcionará apenas como equals() e toString() são sobrepostas para as classs (e profundamente) dos objects comparados.

Isso é importante porque o teste de igualdade na asserção depende de equals() e a mensagem de falha de teste depende de toString() dos objects comparados.
Para classs internas como String , Integer e assim por … não há problema, pois elas substituem equals() e toString() . Portanto, é perfeitamente válido declarar List ou List com assertEquals(Object,Object) .
E sobre este assunto: você tem que replace equals() em uma class porque faz sentido em termos de igualdade de objects, não apenas para tornar as asserções mais fáceis em um teste com JUnit.
Para tornar as afirmações mais fáceis, você tem outras maneiras.
Como boa prática, eu prefiro bibliotecas de asserção / correspondência.

Aqui está uma solução AssertJ .

org.assertj.core.api.ListAssert.containsExactly() é o que você precisa: ele verifica se o grupo atual contém exatamente os valores fornecidos e nada mais, na ordem declarada no javadoc.

Suponha uma class Foo onde você adiciona elementos e onde você pode conseguir isso.
Um teste unitário de Foo que afirma que as duas listas têm o mesmo conteúdo poderia parecer:

 import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; @Test void add() throws Exception { Foo foo = new Foo(); foo.add("One", "Two", "Three"); Assertions.assertThat(foo.getElements()) .containsExactly("One", "Two", "Three"); } 

Um bom argumento é que declarar uma List como esperado é desnecessário: torna a afirmação mais direta e o código mais legível:

 Assertions.assertThat(foo.getElements()) .containsExactly("One", "Two", "Three"); 

Mas as bibliotecas de asserção / correspondência são uma obrigação, porque elas serão realmente mais avançadas.
Suponha agora que Foo não armazena instâncias String s mas Bar s.
Essa é uma necessidade muito comum. Com AssertJ, a afirmação ainda é simples de escrever. Melhor você pode afirmar que o conteúdo da lista é igual, mesmo se a class dos elementos não replace equals()/hashCode() enquanto a maneira JUnit requer que:

 import org.assertj.core.api.Assertions; import static org.assertj.core.groups.Tuple.tuple; import org.junit.jupiter.api.Test; @Test void add() throws Exception { Foo foo = new Foo(); foo.add(new Bar(1, "One"), new Bar(2, "Two"), new Bar(3, "Three")); Assertions.assertThat(foo.getElements()) .extracting(Bar::getId, Bar::getName) .containsExactly(tuple(1, "One"), tuple(2, "Two"), tuple(3, "Three")); }