J'ai récemment utilisé la bibliothèque Hamcrest pour écrire des tests et j'ai réussi, mais maintenant je dois faire quelque chose de plus complexe et j'ai commencé à voir beaucoup de difficultés. Je dois inspecter et vérifier les propriétés des éléments d'une carte. Mon code de production ressemble à ceci:
Map<String, List<MyItem>> map = new HashMap<String, List<MyItem>>();
map.put("one", Arrays.asList(new MyItem("One")));
map.put("two", Arrays.asList(new MyItem("Two")));
map.put("three", Arrays.asList(new MyItem("Three")));
Je veux écrire des codes de test comme les suivants, mais cela ne se compile pas. Il semble que hasEntry de Hamcrest soit paramétré par type, tandis que hasItem et hasProperty n'attendent que Object.
assertThat(map, Matchers.<String, List<MyItem>>hasEntry("one", hasItem(hasProperty("name", is("One")))));
Mon IDE (Eclipse) donne ce message d'erreur: La méthode paramétrée <String, List<HamcrestTest.MyItem>>hasEntry(String, List<HamcrestTest.MyItem>)
de type Matchers
n'est pas applicable pour les arguments (String, Matcher<Iterable<? super Object>>)
Pour une chose, je pense qu'Eclipse est confuse quant à la méthode hasEntry
que je voulais utiliser, elle devrait être hasEntry(org.hamcrest.Matcher<? super K> keyMatcher, org.hamcrest.Matcher<? super V> valueMatcher)
, pas la hasEntry(K key, V value)
.
Dois-je simplement abandonner et obtenir l'élément de la carte et inspecter manuellement chaque propriété? Existe-t-il un moyen plus propre?
Vous pouvez simplement utiliser contains
ou containsInAnyOrder
. Certes, vous devrez répertorier tous les éléments dans List
de cette façon, mais cela fonctionne plus proprement que hasItem
:
@SuppressWarnings("unchecked")
@Test
public void mapTest() {
Map<String, List<MyItem>> map = new HashMap<String, List<MyItem>>();
map.put("one", asList(new MyItem("1"), new MyItem("one")));
assertThat(map, hasEntry(is("one"),
containsInAnyOrder(hasProperty("name", is("one")),
hasProperty("name", is("1")))));
}
Puisque @ t0mppa n'a pas fourni un bon exemple sur la façon d'utiliser les contains
et containsInAnyOrder
de Hamcrest pour cela, voici un petit quelque chose pour commencer:
Map<Integer, String> columns = new HashMap<Integer, String>();
columns.put(1, "ID");
columns.put(2, "Title");
columns.put(3, "Description");
assertThat(columns.values(), contains("ID", "Title", "Description")); // passes
assertThat(columns.values(), contains("ID", "Description", "Title")); // fails
assertThat(columns.values(), containsInAnyOrder("ID", "Description", "Title")); // passes
Notez que contrairement à hasItem
et hasItems
, ceux-ci ne fonctionneront que si vous leur fournissez une liste complète de toutes les valeurs que vous allez comparer. Voir Hamcrest's javadocs pour plus d'informations.
Donc, pour simplifier cela, vous pouvez essayer ceci ...
assertThat((Object)map, (Matcher)Matchers.hasEntry("one", hasItem(hasProperty("name", is("One")))));
en accédant à un type brut, vous obtiendrez un avertissement mais aucune erreur de compilation. Si j'ai utilisé cette astuce dans le passé alors que je ne veux pas m'inquiéter d'obtenir tout le casting juste pour le compilateur.
Vous pouvez également envisager d'utiliser ItIterableContainingInOrder.containingInOrder(new MyItem("One")))
. Cela vérifiera la liste entière et si MyItem
implémente equals
alors vous n'utiliserez pas la réflexion dans vos tests.