JUnit 4 comparar conjuntos

102

¿Cómo afirmaría sucintamente la igualdad de Collectionelementos, específicamente a Seten JUnit 4?

Eqbal
fuente
2
consulte esta publicación SO stackoverflow.com/questions/1086691/collectionassert-in-junit
Teja Kantamneni
¿Está tratando de afirmar que dos conjuntos son iguales entre sí (contienen los mismos elementos) o que dos elementos del mismo conjunto son iguales?
Bill the Lizard
Necesito ver que los elementos de dos conjuntos son iguales
Eqbal

Respuestas:

103

Puede afirmar que los dos Setson iguales entre sí, lo que invoca el 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 );
    }
}

Esto @Testpasará si los dos Sets son del mismo tamaño y contienen los mismos elementos.

Bill el lagarto
fuente
7
Esto no muestra muy buenos resultados en el informe. Si sus toStrings están claramente definidos, es mejor, pero aún no es bueno (una pequeña diferencia puede terminar con una página de texto)
Bill K
Uhm, ¿cómo es que obtengo: java.lang.AssertionError: esperaba: java.util.Hashtable <{CompanyName = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Category = AvrIfd, QuoteId = 434274021.util22, Company WasHashtable < = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Category = AvrIfd, QuoteId = 4342740204922826921}>
Giovanni Botta
3
@Giodude ¿Tiene equalse hashCodeimplementado en la clase que está almacenando en su Hashtable?
Bill the Lizard
Como puede ver, son solo cadenas y un largo ... Estoy probando Avro para serializar y deserializar un mapa y ese es el resultado. Creo que debe haber algo sospechoso en la forma en que se serializan y deserializan las cadenas que hace que la prueba falle, pero parece que no puedo encontrar el problema.
Giovanni Botta
No funcionó para mí a pesar de que estoy comparando dos HashSet <Long>. La respuesta de @MattFriedman realmente funciona para mi caso de uso.
bluecollarcoder
46

Apache commons al rescate de nuevo.

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

Funciona de maravilla. No sé por qué, pero descubrí que con las colecciones lo siguiente assertEquals(coll1, coll2)no siempre funciona. En el caso de que me fallara, tenía dos colecciones respaldadas por Sets. Ni Hamcrest ni Junit dirían que las colecciones eran iguales, aunque yo estaba seguro de que lo eran. Usando CollectionUtils funciona perfectamente.

Matt Friedman
fuente
20
Esto es realmente trivial, la parte difícil es indicar claramente la diferencia a la persona que llama
Bill K
1
La respuesta aceptada es una buena respuesta para la pregunta original (prueba unitaria específicamente para dos conjuntos) pero esta respuesta con CollectionUtils es, creo, una mejor respuesta para el caso más general. No pude comparar una colección y un conjunto a menos que use CollectionUtils.
Jay
16

con hamcrest :

assertThat(s1, is(s2));

con simple aseverar:

assertEquals(s1, s2);

NB: t se utiliza el método equals () de la clase de conjunto de hormigón

dfa
fuente
1
Prefiero este método ya que Hamcrest viene con JUnit 4, por lo que es todo, no se necesitan otras bibliotecas.
JRSofty
2
Es posible que esto no funcione cuando los conjuntos son de diferentes tipos.
Hans-Peter Störr
7

Un caso particularmente interesante es cuando comparas

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

y

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

Hasta ahora, la única solución que veo es convertir ambos en conjuntos

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

O podría compararlos elemento por elemento.


fuente
En realidad, existen varias soluciones para lo que se presenta en las otras respuestas. Los conjuntos son un poco desafortunados por esto, de todos modos, ya que ignoran el orden. ¿Quizás ArrayList?
Hans-Peter Störr
4

Como método adicional basado en matrices ... puede considerar el uso de aserciones de matrices desordenadas en junitx. Aunque el ejemplo de Apache CollectionUtils funcionará, también hay un paquete de extensiones sólidas de aserción:

Yo creo que el

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

El enfoque será mucho más legible y depurable para usted (todas las Colecciones admiten toArray (), por lo que debería ser bastante fácil usar los métodos ArrayAssert.

Por supuesto, la desventaja aquí es que, junitx es un archivo jar adicional o una entrada maven ...

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

Consulta este artículo . Un ejemplo de ahí:

@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);  
}  
romano
fuente
Enlace breve pero excelente, explica muy rápido lo que puede hacer con Junit4-
Johannes
1
El vínculo está roto. ¿Alguna posibilidad de que pueda encontrar una versión archivada en línea o resumir su contenido?
pzp
1

Usando Hamcrest:

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

Esto también funciona cuando los conjuntos tienen diferentes tipos de datos e informa sobre la diferencia en lugar de simplemente fallar.

Hans-Peter Störr
fuente
2
¿Para qué es la importación isIn? IntelliJ no puede resolver la importación con ningún paquete hamcret.
fabien
0

Si desea verificar si una Lista o Conjunto contiene un conjunto de valores específicos (en lugar de compararlo con una colección ya existente), a menudo el método toString de colecciones es útil:

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

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

Esto es un poco más corto que construir primero la colección esperada y compararla con la colección real, y más fácil de escribir y corregir.

(Es cierto que este no es un método particularmente limpio y no puede distinguir un elemento "foo, bar" de dos elementos "foo" y "bar". Pero en la práctica, creo que lo más importante es que sea fácil y rápido escribir pruebas , de lo contrario, muchos desarrolladores simplemente no lo harán sin ser presionados).

Hans-Peter Störr
fuente
Esto hace que el resultado de su prueba unitaria dependa de la implementación de toString from list. Si deciden cambiar el formato, la prueba unitaria dejará de funcionar. No consideraría esto seguro.
Laurens Op 't Zandt
@ LaurensOp'tZandt ¿Te refieres a que Oracle cambie el formato de Collection.toList ()? Ciertamente eso no va a suceder. Sin embargo, tienes razón, eso no es particularmente limpio. Pero en la práctica, tengo la impresión de que lo más importante es que sea muy fácil escribir pruebas.
Hans-Peter Störr
Estoy de acuerdo, creo que el método toString probablemente no será casual. Así que probablemente seguirá funcionando. Solo quería señalar que no es una forma muy limpia. Pero de hecho es muy fácil. Un problema que surge es al comparar conjuntos. Dado que su pedido no está garantizado.
Laurens Op 't Zandt
0

Me gusta la solución de Hans-Peter Störr ... Pero creo que no es del todo correcta. Lamentablemente containsInAnyOrder, no acepta una Collectionde las objetcs para comparar. Entonces tiene que ser una Collectionde Matcherlas siguientes:

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

Las importaciones son:

import static java.util.stream.Collectors.toList;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertThat;
FLUXpartícula
fuente