2016-04-01 5 views
4

私はほとんどのテストにhamcrestを使用していますが、オブジェクトグラフの1レベル下にプロパティをテストできないという問題が発生しました。私のテストケースのハムクレストでネストされたプロパティの深い比較を行う方法はありますか?

final List<Foo> foos= fooRepository.findAll(spec); 
     assertThat(results, is(notNullValue())); 
     assertThat(results, hasItem(hasProperty("id.fooID1", equalTo("FOOID1")))); 

下回るので、ここで私はFOOSのリストに私はFOOID1 .Hereにプロパティid.fooID1のequlaを持っているかどうかを確認したい、私は私のネストされたプロパティ.Thisを確認する1つのレベルをダウンつもりです現在、hamcrestで動作していないので、次のエラーが表示されます。

java.lang.AssertionError: 
Expected: a collection containing hasProperty("id.fooID1", "FOOID1") 
    but: No property "id.fooID1" 
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20) 
    at org.junit.Assert.assertThat(Assert.java:956) 
    at org.junit.Assert.assertThat(Assert.java:923) 

この問題に関するヘルプまたは回避策

答えて

12

ネストすることができますhasProperty呼び出し:

assertThat(results, hasItem(hasProperty("id", hasProperty("fooID1", equalTo("FOOID1"))))); 

が深くネストのために、これは少し扱いに​​くいかもしれません。

+0

それは魅力のように機能しますが、それはより深い階層になると本当に扱いにくいものです。 –

+0

これは素晴らしいものです。 – Loathian

2

問題のAPIソリューションは見つかりませんでしたが、1.3のhamcrestソースで、HasPropertyWithValueマッチャーが実際にネストされたプロパティに潜んでいないことが判明しました。

私は お粗末溶液(見つからないメッセージが正常に動作していないことを確認してください)を作った

import java.beans.PropertyDescriptor; 
import java.lang.reflect.InvocationTargetException; 

import org.hamcrest.Description; 
import org.hamcrest.Matcher; 
import org.hamcrest.TypeSafeDiagnosingMatcher; 
import org.hamcrest.beans.PropertyUtil; 

public class NestedPropertyMatcher<T> extends TypeSafeDiagnosingMatcher<T>{ 

    private final String[] props; 
    private final String path; 
    private final Matcher<?> valueMatcher; 

    @Override 
    public boolean matchesSafely(T bean, Description mismatch) { 
     if (props.length == 1) { 
      return org.hamcrest.beans.HasPropertyWithValue.hasProperty(props[props.length - 1], valueMatcher).matches(bean); 
     } else { 
      Object aux = bean; 
      for (int i = 0; i < props.length - 1; i++) { 
       if (!org.hamcrest.beans.HasProperty.hasProperty(props[i]).matches(aux)) { 
        return false; 
       } else { 
        PropertyDescriptor pd = PropertyUtil.getPropertyDescriptor(props[i], aux); 
        try { 
         aux = pd.getReadMethod().invoke(aux); 
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 
         mismatch.appendText("Exception while trying to access property value: " + e.getLocalizedMessage()); 
         return false; 
        } 
       } 
      } 
      return org.hamcrest.beans.HasPropertyWithValue.hasProperty(props[props.length - 1], valueMatcher).matches(aux); 
     } 
    } 

    private NestedPropertyMatcher(String path, String[] propertiesTokens, Matcher<?> valueMatcher) { 
     this.path = path; 
     this.props = propertiesTokens; 
     this.valueMatcher = valueMatcher; 
    } 

    public static <T> Matcher<T> hasPathProperty(String propertyPath, Matcher<?> valueMatcher) { 
     String[] props = propertyPath.split("\\."); 
     return new NestedPropertyMatcher<T>(propertyPath, props, valueMatcher); 
    } 

    @Override 
    public void describeTo(Description description) { 
     description.appendText("hasProperty(").appendValue(path).appendText(", ").appendDescriptionOf(valueMatcher).appendText(") did not found property"); 
    } 
} 

、hamcrest人々は私より良い仕事をするだろうことをかなり確信してますが私はこのコードがあなたのために十分であると思います。

+0

衝突を避けるために、マッチャー関数名を変更しました。 –

4

私はあなたがこのシンプルなユーティリティメソッドで期待される結果を達成した:これは、任意の助けである場合

assertThat(bean, hasGraph("beanProperty.subProperty.subSubProperty", notNullValue())); 

チェック:

私は使用することができる午前
private static <T> Matcher<T> hasGraph(String graphPath, Matcher<T> matcher) { 

    List<String> properties = Arrays.asList(graphPath.split("\\.")); 
    ListIterator<String> iterator = 
     properties.listIterator(properties.size()); 

    Matcher<T> ret = matcher; 
    while (iterator.hasPrevious()) { 
     ret = hasProperty(iterator.previous(), ret); 
    } 
    return ret; 
} 

は次のように主張します

+1

ニース、明確かつ簡潔です。 – SimonDever

関連する問題