J'aimerais utiliser hamcrest pour affirmer que deux cartes sont égales, c'est-à-dire qu'elles ont le même jeu de clés pointant vers les mêmes valeurs.
Ma meilleure hypothèse actuelle est:
assertThat( affA.entrySet(), hasItems( affB.entrySet() );
qui donne:
La méthode assertThat (T, Matcher) dans le type Assert n'est pas applicable pour les arguments (Set>, Matcher >>>)
J'ai également examiné les variantes de includesAll et quelques autres fournies par les packages hamcrest. Est-ce que quelqu'un peut-il me montrer la bonne direction? Ou dois-je écrire un matcher personnalisé?
Le chemin le plus court que j'ai trouvé est deux déclarations:
assertThat( affA.entrySet(), everyItem(isIn(affB.entrySet())));
assertThat( affB.entrySet(), everyItem(isIn(affA.entrySet())));
Mais vous pouvez probablement aussi faire:
assertThat(affA.entrySet(), equalTo(affB.entrySet()));
en fonction des implémentations des cartes.
UPDATE: il existe en réalité une instruction qui fonctionne indépendamment des types de collection:
assertThat(affA.entrySet, both(everyItem(isIn(affB.entrySet()))).and(containsInAnyOrder(affB.entrySet())));
Parfois, Map.equals()
est suffisant. Mais parfois, vous ne savez pas que les types de Map
s sont renvoyés par le code soumis à des tests. Par conséquent, vous ne savez pas si .equals()
comparera correctement la mappe de type inconnu renvoyée par le code à la mappe construite par vous. Ou vous ne voulez pas lier votre code avec de tels tests.
De plus, construire une carte séparément pour comparer le résultat avec celui-ci est un IMHO pas très élégant:
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));
Je préfère utiliser des 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))
));
Je dois définir moi-même hasSize()
:
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");
}
};
}
Et il existe une autre variante de hasEntry()
qui prend les correspondants comme paramètres au lieu des valeurs exactes de clé et de valeur. Cela peut être utile si vous avez besoin de quelque chose d'autre que le test d'égalité de chaque clé et valeur.
Une autre option disponible consiste à utiliser l’extension Cirneco pour Hamcrest. Il a hasSameKeySet()
(ainsi que d'autres correspondants pour les "collections" de goyave) . Selon votre exemple, ce sera:
assertThat(affA, hasSameKeySet(affB));
Vous pouvez utiliser la dépendance suivante pour un projet basé sur JDK7:
<dependency>
<groupId>it.ozimov</groupId>
<artifactId>Java7-hamcrest-matchers</artifactId>
<version>0.7.0</version>
</dependency>
ou les suivants si vous utilisez JDK8 ou supérieur:
<dependency>
<groupId>it.ozimov</groupId>
<artifactId>Java8-hamcrest-matchers</artifactId>
<version>0.7.0</version>
</dependency>
Je préfère utiliser Guava ImmutableMap . Ils supportent Map.equals()
et sont faciles à construire. La seule astuce consiste à spécifier explicitement les paramètres de type, puisque hamcrest assumera le type ImmutableMap
.
assertThat( actualValue,
Matchers.<Map<String, String>>equalTo( ImmutableMap.of(
"key1", "value",
"key2", "other-value"
) ) );
Cela fonctionne comme un charme et ne nécessite pas deux affirmations comme la réponse acceptée.
assertThat( actualData.entrySet().toArray(),
arrayContainingInAnyOrder(expectedData.entrySet().toArray()) );
Si vous avez besoin de comparer un ensemble de résultats avec les attentes et si vous choisissez d'utiliser assertj library, vous pouvez le faire:
// 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);
Notez que containsAllEntriesOf
ne compare pas les cartes pour l’égalité. Si votre code de production renvoie en réalité un Map<K, V>
, vous pouvez ajouter une vérification des clés assertThat(results).containsOnlyKeys((K[]) expectations.keySet().toArray());
.
Une méthode assez simple consiste à utiliser une méthode utilitaire issue de la classe com.google.common.collect.Maps de Guava.
assertThat(Maps.difference(map1,map2).areEqual(),is(true));
Hamcrest a maintenant une Matcher
pour la collection de taille.
org.hamcrest.collection.IsCollectionWithSize