2015-07-20 30 views
8

İç içe geçmiş harita değerini kontrol etmesi gereken bir birim testim var. Girişimi çekerek ve temeldeki Map ile eşleşerek çalışmamı onaylayabilirim, ancak iddianın ne yaptığını göstermenin açık bir yolunu arıyordum. İşte çok basitleştirilmiş bir testtir:Harita, yol gösterici ile eşleşiyor Harita içeriyor

import static org.hamcrest.MatcherAssert.assertThat; 
import static org.hamcrest.Matchers.hasEntry; 

import java.util.HashMap; 
import java.util.Map; 

import org.junit.Test; 

public class MapContainsMapTest { 
    @Test 
    public void testMapHasMap() { 
     Map<String, Object> outerMap = new HashMap<String, Object>(); 
     Map<String, Object> nestedMap = new HashMap<String, Object>(); 
     nestedMap.put("foo", "bar"); 
     outerMap.put("nested", nestedMap); 

     // works but murky 
     assertThat((Map<String, Object>) outerMap.get("nested"), hasEntry("foo", "bar")); 
     // fails but clear 
     assertThat(outerMap, hasEntry("nested", hasEntry("foo", "bar"))); 
    } 
} 

sorunun ne kullanmak istediğim hasEntry(Matcher<? super K> keyMatcher, Matcher<? super V> valueMatcher) iken hasEntry(K key, V value) kullanılarak karşılaştırılır ediliyor dış haritasıdır görünüyor. İkinci formu kullanmak için iddiayı nasıl zorlayacağımı bilmiyorum.

Şimdiden teşekkürler. Eğer çirkin döküm gerekmez Map<String, Map<String, Object>> olarak outerMap bildirirseniz

class SubMapMatcher extends BaseMatcher<Map<?,?>> { 

private Object key; 
private Object subMapKey; 
private Object subMapValue; 

public SubMapMatcher(Object key, Object subMapKey, Object subMapValue) { 
    super(); 
    this.key = key; 
    this.subMapKey = subMapKey; 
    this.subMapValue = subMapValue; 
} 

@Override 
public boolean matches(Object item) { 

    Map<?,?> map = (Map<?,?>)item; 

    if (!map.containsKey(key)) { 
     return false; 
    } 

    Object o = map.get(key); 

    if (!(o instanceof Map<?,?>)) { 
     return false; 
    } 

    Map<?,?> subMap = (Map<?,?>)o; 
    return subMap.containsKey(subMapKey) && subMap.get(subMapKey).equals(subMapValue); 
} 

@Override 
public void describeTo(Description description) { 
    description.appendText(String.format("contains %s -> %s : %s", key, subMapKey, subMapValue)); 
} 

public static SubMapMatcher containsSubMapWithKeyValue(String key, String subMapKey, String subMapValue) { 
    return new SubMapMatcher(key, subMapKey, subMapValue); 
} 

} 
+0

hasEntry ' "_It sorun dış haritası ..._ kullanılarak karşılaştırılır ediliyor gibi görünüyor"(vardır ("anahtar") olduğu ("değer"))' örneğin neden olacak kullanabilirsiniz kullanılacak ikinci form. Belki 'equalTo 'eşleştiricisini' is' yerine kullanabilirsin, ama her iki şekilde de okunabilirlik pencereden dışarı çıkar. – mystarrocks

+0

Sorun, dış testte olduğu için, equalTo ("nested") gibi bir şeye ihtiyacım var ... 'Ama bu, dış harita türünü' Map olarak değiştirmedikçe çalışmaz > ' –

cevap

2

Muhtemelen bunun için böyle bir şey (NPES gizlenen, dikkat) Yeni bir Matcher uzanacak. Şunun gibi: Yalnızca buna göre outerMap ayarlamak bildiriminde değerler olarak Map<String, Object> koymak istiyorsanız

public class MapContainsMapTest { 

    @Test 
    public void testMapHasMap() { 
     Map<String, Map<String, Object>> outerMap = new HashMap<>(); 
     Map<String, Object> nestedMap = new HashMap<>(); 
     nestedMap.put("foo", "bar"); 
     outerMap.put("nested", nestedMap); 

     assertThat(outerMap.get("nested"), hasEntry("foo", "bar")); 
    } 
} 
+0

Teşekkürler, bu cevap çalışıyor. Bununla birlikte, herhangi bir yuvalanma seviyesine izin vermek için bunu genişletip genişletemeyeceğimi görmek istiyorum. –

+0

Yeterince kolay geliyor, 'Nesne değeri, Dize ... tuşları' gibi bir imzayı kullanabilirsiniz. Daha sonra tuşların üzerinden yineleyin, sonuncuya ulaşıncaya kadar alt-haritayı alın (veya değeriniz olarak null ya da haritasız olarak yanıltın) ve değeri kontrol edin. Örneğin, 'includeValueInSubMap (someValue, map0Key, map1Key, map2Key);' Elbette kişisel olarak bir anahtar için standart bir Harita kullanmanızı önermeyeceğim -> "değer OR alt-haritası" eşlemesi, ancak bunun yerine genel bir niteliğe sahip olan daha spesifik bir şey değer türleri (alt harita ve değerlere sahip bir harita etkili bir ağaçtır, bir şey bulmak kolay olmalıdır). –

2

:

+0

@DanGetz Dökümü kaldırırsam derleme yapmaz, outerMap Map > olarak bildirilmelidir. –

+0

@DanGetz daha iyi? –

+0

Örneğim, benim testimin basitleştirilmiş bir versiyonudur, burada outerMap tüm girişlerin harita olmadığı bir JSON nesnesidir, bu yüzden harita beyanını yazılı olarak tutmalıyım. –

2

. Sonra

@Test 
public void testMapHasMap() { 
    Map<String, Map<String, Object>> outerMap = new HashMap<>(); 
    Map<String, Object> nestedMap = new HashMap<String, Object>(); 
    nestedMap.put("foo", "bar"); 
    outerMap.put("nested", nestedMap); 

    Object value = "bar"; 
    assertThat(outerMap, hasEntry(equalTo("nested"), hasEntry("foo", value))); 
} 

Object value = "bar"; derleme nedenlerle gereklidir yapabilirsiniz. Alternatif

assertThat(outerMap, 
    hasEntry(equalTo("nested"), Matchers.<String, Object> hasEntry("foo", "bar"))); 
+0

Örneğim, dış girdinin tüm girişlerin harita olmadığı bir JSON nesnesi olduğu testimin basitleştirilmiş bir sürümüdür, bu yüzden harita bildirimini yazılı olarak tutmam gerekir. –