2010-07-13 6 views
101

Cómo hacer afirmaciones sobre una lista en un JUnit caso de prueba? No solo el tamaño de la lista, sino también el contenido de la lista.Afirmar sobre una lista en Junit

+0

Me gusta usar 'assertArrayEquals' hoy en día. Úselo en combinación con 'List # toArray'. – Thibstars

Respuesta

18

Esta es una respuesta heredada, adecuada para JUnit 4.3 y siguientes. La versión moderna de JUnit incluye un mensaje de error legible incorporado en el método assertThat. Prefiere otras respuestas sobre esta pregunta, si es posible.

List<E> a = resultFromTest(); 
List<E> 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 el registro, como @ Pablo mencionó en su comentario a esta respuesta, dos List s son iguales:

si y sólo si el objeto especificado es también una lista, ambas listas tienen el mismo tamaño, y todos los pares correspondientes de elementos en las dos listas son iguales. (Dos elementos e1 y e2 son iguales si (e1==null ? e2==null : e1.equals(e2)).) En otras palabras, dos listas se definen como iguales si contienen los mismos elementos en el mismo orden. Esta definición asegura que el método equals funciona correctamente en diferentes implementaciones de la interfaz List.

Ver el JavaDocs of the List interface.

+1

¿Quiere decir expected.equals (a) se encargará de afirmar los objetos que contiene la lista? – Kamal

+1

De la lista javadoc: Compara el objeto especificado con esta lista para la igualdad. Devuelve verdadero si y solo si el objeto especificado también es una lista, ambas listas tienen el mismo tamaño y todos los pares correspondientes de elementos en las dos listas son iguales. (Dos elementos e1 y e2 son iguales si (e1 == nulo? E2 == nulo: e1.equals (e2)).) En otras palabras, dos listas se definen como iguales si contienen los mismos elementos en el mismo orden . Esta definición asegura que el método equals funciona correctamente en diferentes implementaciones de la interfaz de la Lista. –

+0

@Kamal, sí (ver el comentario de Paul y mi edición). –

104

Me doy cuenta de que esto fue preguntado hace un par de años, probablemente esta característica no existía entonces. Pero ahora, es fácil simplemente hacer esto:

@Test 
public void test_array_pass() 
{ 
    List<String> actual = Arrays.asList("fee", "fi", "foe"); 
    List<String> expected = Arrays.asList("fee", "fi", "foe"); 

    assertThat(actual, is(expected)); 
    assertThat(actual, is(not(expected))); 
} 

Si usted tiene una versión reciente de Junit instalado con hamcrest, sólo tiene que añadir estas importaciones:

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

+1

@ djeikyb- tiene una buena característica. Gracias por la actualización. – Kamal

+2

'System.out.println (real == expected);' devolverá false, pero 'System.out.println (actual.equals (expected));' devolverá true. – Catfish

+0

@Catfish, sí, eso es confuso ¿no? Creo que estaba demostrando que el matcher está usando '.equals (..)' en lugar de '=='? – djeikyb

7

Si lo hace no importa el orden de los elementos, recomiendo ListAssert.assertEquals en junit-addons.

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

Para los usuarios de Maven perezosos:

<dependency> 
     <groupId>junit-addons</groupId> 
     <artifactId>junit-addons</artifactId> 
     <version>1.4</version> 
     <scope>test</scope> 
    </dependency> 
+6

Nota: Si no le importa el orden de los elementos, debe usar un conjunto o colección, no una lista. – Barett

+9

Estoy de acuerdo. Esta biblioteca es asquerosa ¿Por qué demonios ListAssert.assertEquals() sería predeterminado? – Ryan

0

No reinventar la rueda!

Hay una biblioteca de código de Google que hace esto para usted: Hamcrest

[Hamcrest] proporciona una biblioteca de objetos matcher (también conocido como limitaciones o predicados) que permiten las reglas 'partidos' que se defina de forma declarativa, a ser utilizado en otros marcos. Los escenarios típicos incluyen marcos de prueba, bibliotecas burlonas y reglas de validación UI.

0

si no desea construir una lista de arreglo, puede intentar esto también

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

No transformar a cuerda y comparar.Esto no es bueno para el rendimiento. En el junit, dentro Corematchers, hay una matcher para este =>hasItems

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

Ésta es la mejor manera que conozco para comprobar los elementos de una lista.

+1

Debe ser la respuesta elegida, con una nota: también debe verificar que no haya más elementos en la lista además de los que desee. Tal vez use: 'Assert.assertEquals (4, yourList.size());' – yoni

+0

o con una sola línea: 'assertThat (yourList.toArray(), arrayContainingInAnyOrder (1,2,3,4,5));' – user1778602

3
List<Integer> figureTypes = new ArrayList<Integer>(
          Arrays.asList(
           1, 
           2 
          )); 

List<Integer> figureTypes2 = new ArrayList<Integer>(
          Arrays.asList(
           1, 
           2)); 

assertTrue(figureTypes .equals(figureTypes2)); 
0

No es esto, todas las respuestas anteriores dan la solución exacta para comparar dos listas de objetos. La mayoría de los enfoques anteriores puede ser útil en la siguiente límite de comparaciones sólo - Tamaño comparación - Comparativa de referencia

Pero si tenemos mismas listas de tamaño de los objetos y diferentes datos sobre los objetos de nivel, entonces se acerca a esta comparación no ayudarán .

Creo que el siguiente enfoque funcionará perfectamente con la anulación de iguales y el método de código hash en el objeto definido por el usuario.

Utilicé Xstream lib para anular equals y hashcode pero también podemos anular equals y hashcode por out logics/comparison.

Aquí está el ejemplo para su referencia

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<TestClass> testList1 = new ArrayList<TestClass>(); 
     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<TestClass> testList2 = new ArrayList<TestClass>(); 
     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<TestClass> clist1, List<TestClass> clist2) { 
     return clist1.size() != clist2.size() || !clist1.equals(clist2); 
     } 
    } 

Lo más importante es que se puede pasar por alto los campos de anotación (@XStreamOmitField) si no desea incluir cualquiera de los campos en la verificación de la igualdad Objetos. Hay muchas Anotaciones como esta para configurar, así que echa un vistazo profundo a las anotaciones de esta lib.

Estoy seguro de que esta respuesta le ahorrará tiempo para identificar el enfoque correcto para comparar dos listas de objetos :). Comente si ve algún problema al respecto.

Cuestiones relacionadas