web-dev-qa-db-ja.com

Hamcrestを使用した等値性のマッピング

Hamcrestを使用して、2つのマップが等しいこと、つまり、同じ値を指す同じキーセットを持っていることを表明したいと思います。

私の現在の最良の推測は次のとおりです。

assertThat( affA.entrySet(), hasItems( affB.entrySet() );

与えるもの:

タイプAssertのメソッドassertThat(T、Matcher)は、引数(Set>、Matcher >>>)には適用されません。

ContainsAllのバリエーション、およびhamcrestパッケージで提供されるその他のバリエーションも調べました。誰かが私を正しい方向に向けることができますか?または、カスタムマッチャーを作成する必要がありますか?

48
mo-seph

私が思いついた最短の方法は、2つのステートメントです。

assertThat( affA.entrySet(), everyItem(isIn(affB.entrySet())));
assertThat( affB.entrySet(), everyItem(isIn(affA.entrySet())));

しかし、おそらくあなたもできる:

assertThat(affA.entrySet(), equalTo(affB.entrySet()));

マップの実装に依存します。

更新:実際には、コレクションの種類に関係なく機能するステートメントが1つあります。

assertThat(affA.entrySet, both(everyItem(isIn(affB.entrySet()))).and(containsInAnyOrder(affB.entrySet())));
51

時にはMap.equals()で十分です。ただし、テスト中のコードによってMapsの型が返されることがわからない場合があるため、.equals()がコードで返された不明な型のマップをmapと適切に比較するかどうかわかりませんあなたによって構築されました。または、そのようなテストでコードをバインドしたくない場合。

さらに、結果を比較するためにマップを個別に構築することは、非常にエレガントではありません。

_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));
_

私はマッチャーの使用を好みます:

_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))
));
_

私は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");
        }
    };
}
_

また、キーと値の正確な値の代わりにマッチャーをパラメーターとして使用するhasEntry()の別のバリアントがあります。これは、すべてのキーと値の等価性テスト以外のものが必要な場合に役立ちます。

37
Alexey Tigarev

現在利用可能な別のオプションは、Hamcrestに Cirneco拡張 を使用することです。 hasSameKeySet() (グアバ「コレクション」の他のマッチャーと同様)を持っています。あなたの例によると、それは次のようになります:

assertThat(affA, hasSameKeySet(affB));

JDK7ベースのプロジェクトでは、次の依存関係を使用できます。

<dependency>
  <groupId>it.ozimov</groupId>
  <artifactId>Java7-hamcrest-matchers</artifactId>
  <version>0.7.0</version>
</dependency>

または、JDK8以上を使用している場合は次のとおりです。

<dependency>
  <groupId>it.ozimov</groupId>
  <artifactId>Java8-hamcrest-matchers</artifactId>
  <version>0.7.0</version>
</dependency>
2
JeanValjean

Guava ImmutableMap の使用を好みます。それらはMap.equals()をサポートし、簡単に構築できます。唯一のトリックは、hamcrestがImmutableMap型を想定するため、型パラメーターを明示的に指定することです。

assertThat( actualValue,
            Matchers.<Map<String, String>>equalTo( ImmutableMap.of(
                "key1", "value",
                "key2", "other-value"
) ) );
2
Huuu

非常に簡単な方法は、Guavaのcom.google.common.collect.Mapsクラスのユーティリティメソッドを使用することです。

assertThat(Maps.difference(map1,map2).areEqual(),is(true));
1

これは魅力のように機能し、受け入れられた答えのような2つのアサーションを必要としません。

assertThat( actualData.entrySet().toArray(), 
    arrayContainingInAnyOrder(expectedData.entrySet().toArray()) );
0
Bryan Correll

結果セットを期待値と比較する必要がある場合、および assertj ライブラリを使用することを選択した場合、これを行うことができます。

_// 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);
_

containsAllEntriesOfはマップが等しいかどうかを比較しないことに注意してください。実動コードが実際に_Map<K, V>_を返す場合、キーassertThat(results).containsOnlyKeys((K[]) expectations.keySet().toArray());のチェックを追加することができます。

0

Hamcrestには、サイズコレクション用のMatcherがあります。

org.hamcrest.collection.IsCollectionWithSize

0
ZPalazov