13

数日間、私は現在 Junit の Matchers 機能を使用しています。すべて正常に動作していますが、比較にコンパレータを使用し、オブジェクトの equals メソッドに依存しないマッチャーを探しています。

交換したい

Assert.assertThat(one, CoreMatchers.equalTo(two)

(疑似コード)のようなもので

Assert.assertThat(eins, CoreMatchers.equalTo(operand, new MyComparator())

すぐに使える簡単なソリューションがあるかどうか知っていますか? 私はグーグルで見つけられなかったので、書きたくありません。

4

4 に答える 4

14

これは Hamcrest 2.0.0.0+ でサポートされるようになりました。

たとえば、 org.hamcrest.comparator.ComparatorMatcherBuilderクラスを使用してこれを実現できます。

ComparatorMatcherBuilder builder = ComparatorMatcherBuilder.comparedBy(equivalenceComparator);
Assert.assertThat(eins, builder.comparesEqualTo(operand));
于 2015-03-25T12:47:55.760 に答える
1

私は hamcrest 1.3 で同じ問題を抱えていましたが、IsEqual-Matcher のコードに従いますが、Object#equals() の代わりに特定の Comparator を使用するマッチャーを作成することで解決しました。

import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import org.junit.Assert;

import java.lang.reflect.Array;
import java.util.Comparator;

/**
 * Is the value equal to another value, as tested by the
 * given Comparator?<br/>
 * Based on the example of {@link org.hamcrest.core.IsEqual}.
 *
 * @author Serhat Cinar
 */
public class IsEqualWithComparator<T> extends BaseMatcher<T> {
    private final Object expectedValue;
    private final Comparator<T> comparator;

    public IsEqualWithComparator(T equalArg, Comparator<T> comparator) {
        expectedValue = equalArg;
        this.comparator = comparator;
    }

    @Override
    public boolean matches(Object actualValue) {
        return areEqual(actualValue, expectedValue, comparator);
    }

    @Override
    public void describeTo(Description description) {
        description.appendValue(expectedValue);
    }

    private static boolean areEqual(Object actual, Object expected, Comparator comparator) {
        if (actual == null) {
            return expected == null;
        }

        if (expected != null && isArray(actual)) {
            return isArray(expected) && areArraysEqual(actual, expected, comparator);
        }

        return comparator.compare(actual, expected) == 0;
    }

    private static boolean areArraysEqual(Object actualArray, Object expectedArray, Comparator comparator) {
        return areArrayLengthsEqual(actualArray, expectedArray) && areArrayElementsEqual(actualArray, expectedArray, comparator);
    }

    private static boolean areArrayLengthsEqual(Object actualArray, Object expectedArray) {
        return Array.getLength(actualArray) == Array.getLength(expectedArray);
    }

    private static boolean areArrayElementsEqual(Object actualArray, Object expectedArray, Comparator comparator) {
        for (int i = 0; i < Array.getLength(actualArray); i++) {
            if (!areEqual(Array.get(actualArray, i), Array.get(expectedArray, i), comparator)) {
                return false;
            }
        }
        return true;
    }

    private static boolean isArray(Object o) {
        return o.getClass().isArray();
    }

    @Factory
    public static <T> Matcher<T> equalTo(T operand, Comparator<T> comparator) {
        return new IsEqualWithComparator<>(operand, comparator);
    }

    public static void main(String argv[]) {
        Assert.assertThat("abc", IsEqualWithComparator.equalTo("ABC", new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.equalsIgnoreCase(o2) ? 0 : -1;
            }
        }));
    }
}
于 2016-12-09T13:33:35.877 に答える
0

ハムクレストでそれを行うための何かを私は知りません。カスタムマッチャーを作成する必要がある場合があります。考慮すべき 1 つの点:equalsが返されない場合true、オブジェクトは等しいか? 特定のプロパティをテストしている場合、カスタム マッチャーはFeatureMatcher( Hamcrest を使用してフィールドを照合する簡単な方法はありますか? ) としてより明確になる可能性があります。たとえば、テストが予想されるラベルの場合:

assertThat(eins, equalToUnderComparison("1", new LabelComparator());

次のように明確になる場合があります。

assertThat(eins, hasLabel(eq("1")));

カスタムマッチャーを書くことは多くのコードを必要とせず (カスタムマッチャーを書く)、コードがより読みやすくなるのであれば、それを避ける理由はありません。

于 2013-08-03T12:26:34.750 に答える