java - org - Mapa de igualdad usando Hamcrest
import static org hamcrest matchers equalto (8)
Me gustaría utilizar Hamcrest para afirmar que dos mapas son iguales, es decir, tienen el mismo conjunto de claves apuntando a los mismos valores.
Mi mejor conjetura actual es:
assertThat( affA.entrySet(), hasItems( affB.entrySet() );
lo que da:
El método assertThat (T, Matcher) en el tipo Assert no es aplicable para los argumentos (Set>, Matcher >>>)
También he investigado las variaciones de containsAll y algunas otras proporcionadas por los paquetes de hamcrest. ¿Alguien puede señalarme en la dirección correcta? ¿O tengo que escribir un marcador personalizado?
Algunas veces Map.equals()
es suficiente. Pero a veces no sabes los tipos de Map
s devueltos por el código en las pruebas, por lo que no sabes si .equals()
comparará correctamente ese mapa de tipo desconocido devuelto por el código con el mapa creado por ti. O no desea vincular su código con tales pruebas.
Además, construir un mapa por separado para comparar el resultado con él es IMHO no muy elegante:
Map<MyKey, MyValue> actual = methodUnderTest();
Map<MyKey, MyValue> expected = new HashMap<MyKey, MyValue>();
expected.put(new MyKey(1), new MyValue(10));
expected.put(new MyKey(2), new MyValue(20));
expected.put(new MyKey(3), new MyValue(30));
assertThat(actual, equalTo(expected));
Prefiero usar machers:
import static org.hamcrest.Matchers.hasEntry;
Map<MyKey, MyValue> actual = methodUnderTest();
assertThat(actual, allOf(
hasSize(3), // make sure there are no extra key/value pairs in map
hasEntry(new MyKey(1), new MyValue(10)),
hasEntry(new MyKey(2), new MyValue(20)),
hasEntry(new MyKey(3), new MyValue(30))
));
Tengo que definir hasSize()
yo mismo:
public static <K, V> Matcher<Map<K, V>> hasSize(final int size) {
return new TypeSafeMatcher<Map<K, V>>() {
@Override
public boolean matchesSafely(Map<K, V> kvMap) {
return kvMap.size() == size;
}
@Override
public void describeTo(Description description) {
description.appendText(" has ").appendValue(size).appendText(" key/value pairs");
}
};
}
Y hay otra variante de hasEntry()
que toma los matchers como parámetros en lugar de valores exactos de clave y valor. Esto puede ser útil en caso de que necesite algo más que la prueba de igualdad de cada clave y valor.
Esto funciona como un amuleto y no requiere dos afirmaciones como la respuesta aceptada.
assertThat( actualData.entrySet().toArray(),
arrayContainingInAnyOrder(expectedData.entrySet().toArray()) );
Estoy a favor de usar Guava ImmutableMap . Map.equals()
y son fáciles de construir. El único truco es especificar explícitamente los parámetros de tipo, ya que hamcrest asumirá el tipo ImmutableMap.
assertThat( actualValue,
Matchers.<Map<String, String>>equalTo( ImmutableMap.of(
"key1", "value",
"key2", "other-value"
) ) );
Hamcrest ahora tiene un Matcher
para la colección de tallas.
org.hamcrest.collection.IsCollectionWithSize
La forma más corta en que me he encontrado es con dos afirmaciones:
assertThat( affA.entrySet(), everyItem(isIn(affB.entrySet())));
assertThat( affB.entrySet(), everyItem(isIn(affA.entrySet())));
Pero probablemente también puedas:
assertThat(affA.entrySet(), equalTo(affB.entrySet()));
dependiendo de las implementaciones de los mapas.
ACTUALIZAR: en realidad hay una declaración que funciona independientemente de los tipos de colección:
assertThat(affA.entrySet, both(everyItem(isIn(affB.entrySet()))).and(containsInAnyOrder(affB.entrySet())));
Otra opción disponible ahora es usar la extensión Cirneco para Hamcrest. Tiene hasSameKeySet()
(así como otros emparejadores para "colecciones" de Guava). De acuerdo con su ejemplo, será:
assertThat(affA, hasSameKeySet(affB));
Puede usar la siguiente dependencia para un proyecto basado en JDK7:
<dependency>
<groupId>it.ozimov</groupId>
<artifactId>java7-hamcrest-matchers</artifactId>
<version>0.7.0</version>
</dependency>
o lo siguiente si está usando JDK8 o superior:
<dependency>
<groupId>it.ozimov</groupId>
<artifactId>java8-hamcrest-matchers</artifactId>
<version>0.7.0</version>
</dependency>
Si necesita comparar un conjunto de resultados con las expectativas y si elige usar la biblioteca assertj , puede hacer esto:
// put set of expected values by your test keys
Map<K, V> expectations = ...;
// for each test key get result
Map<K, V> results = expectations.keySet().stream().collect(toMap(k -> k, k -> getYourProductionResult(k)));
assertThat(results).containsAllEntriesOf(expectations);
Tenga en cuenta que containsAllEntriesOf
no compara los mapas para la igualdad. Si su código de producción devuelve en realidad un Map<K, V>
, puede agregar un cheque para las claves assertThat(results).containsOnlyKeys((K[]) expectations.keySet().toArray());
Una forma bastante simple es usar un método de utilidad de la clase com.google.common.collect.Maps de Guava.
assertThat(Maps.difference(map1,map2).areEqual(),is(true));