2015-05-13 5 views
9

Diciamo che ho una mappa:Utilizzando hamcrest per abbinare mappa contiene le voci di diversi tipi

Map<String,Object> map1 = new HashMap<String,Object>(); 
map1.put("foo1","foo1"); 
map1.put("foo2", Arrays.asList("foo2","bar2")); 

Ora mi piacerebbe usare Hamcrest matchers per verificare i valori della mappa. Se questa fosse una stringa Mappa <, String> vorrei fare qualcosa di simile a questo:

assertThat(map1, hasEntry("foo1", "foo1")); 

Tuttavia, mi sono bloccato quando si cerca di utilizzare questo con la mappa in cui le voci della mappa potrebbe essere una stringa o un Elenco di valori. Funziona per la prima voce:

assertThat(map1, hasEntry("foo1", (Object)"foo1")); 

Per la seconda voce non riesco a capire come impostare i Matcher.

EDIT:

Ho provato anche questo, ma produce un avviso del compilatore.

assertThat(
      map1, 
      hasEntry(
        "foo2", 
        contains(hasProperty("name", is("foo2")), 
          hasProperty("name", is("bar2"))))); 

"Il metodo assertThat (T, Matcher) nel tipo asserzione non è applicabile per gli argomenti (Mappa, Matcher >>>)"

(Quello qui sopra è la soluzione qui: Hamcrest compare collections)

+0

Quale versione di Java usi? – medvedev1088

+0

versione 1.7 del JDK – acvcu

risposta

5

Non è possibile eseguire questa operazione elegantemente con Hamcrest hasEntry poiché eseguirà il controllo del tipo quando si tenta di utilizzare i parametri di corrispondenza sugli elenchi. L'opzione più semplice credo è quello di fare qualcosa di simile:

@Test 
public void test() { 
    Map<String, Object> map1 = new HashMap<>(); 
    map1.put("foo1", "foo1"); 
    map1.put("foo2", Arrays.asList("foo2", "bar2")); 

    assertThat(map1, hasEntry("foo1", "foo1")); 
    assertThat(map1, hasListEntry(is("foo2"), containsInAnyOrder("foo2", "bar2"))); 
} 

@SuppressWarnings("unchecked") 
public static org.hamcrest.Matcher<java.util.Map<String, Object>> hasListEntry(org.hamcrest.Matcher<String> keyMatcher, org.hamcrest.Matcher<java.lang.Iterable<?>> valueMatcher) { 
    Matcher mapMatcher = org.hamcrest.collection.IsMapContaining.<String, List<?>>hasEntry(keyMatcher, valueMatcher); 
    return mapMatcher; 
} 

hasListEntry è qui solo per evitare che l'errore del compilatore. Assegnazione non controllata è il motivo per cui è necessario @SuppressWarnings ("deselezionato"). Ad esempio, puoi inserire questo metodo statico nell'utilità di test comune.

+0

L'unica modifica che dovevo fare era containsInAnyOrder ((Object) "foo2", (Object) "bar2") ... non sono sicuro del perché le stringhe sono oggetti. – acvcu

+0

@acvcu: È perché stai recuperando elementi dalla mappa come 'Oggetto', non' String'. Sì, sono ancora istanze 'String', ma vengono considerate come' Object' (analogo a 'Object entry =" foo ";'). – Makoto

0

Prova in questo modo è possibile utilizzare ImmutableMap

assertThat(actualValue, 
      Matchers.<Map<String, Object>>equalTo(ImmutableMap.of(
       "key1", "value", 
       "key2", "arrayrelated values" 
))); 

spero che lavorerà per voi.

+0

L'idea qui è usare Hamcrest, e non farlo in questo modo. Mentre questo approccio funzionerebbe * senza * Hamcrest, dubito che ciò che l'OP sta cercando. – Makoto

+0

@Makoto Ho aggiornato la mia risposta che corrisponde al requisito come basato su Hemcrest Matcher –

+0

Ci sono più problemi che ho trovato con questa proposta. Prima devi lanciare i valori con (Object), e in secondo luogo non capisco come stai cercando di mostrare la collezione nel valore di "key2" ... – acvcu