2013-07-30 10 views
8

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

私はあなたが簡単にはボックスソリューションの外に存在するかどうかを知っていますか何か

(擬似コード)のような
Assert.assertThat(eins, CoreMatchers.equalTo(operand, new MyComparator()) 

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

を交換したいですか?私はgoogleで1つを見つけられなかったし、1つを書きたいと思わない。

+2

ずにアサーションを処理することができますorg/hamcrest/BaseMatcher.html)。 –

+1

それは存在しません驚いています。次の人が使用できるように、あなたのソリューションを投稿してください。 –

答えて

0

私はハムクレストでこれを行うことについて何も知らない。カスタムマッチャーを記述する必要があるかもしれません。考慮する1つの点:equalstrueを返さない場合、オブジェクトは等しいか?特定のプロパティをテストしている場合、カスタムマッチャーはFeatureMatcherIs there a simple way to match a field using Hamcrest?)として明確になります。例えば、テストは、予想されるラベルにある場合:カスタムマッチャを書くことは多くのコード(Writing custom matchersを)取るとする理由はありませんしません

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

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

はとして明確かもしれコードを読みやすくするなら、それを避けてください。

+0

ビジネスロジックに基づいてequals/hashCodeを実装できないJPAモデルインスタンスの場合は非常に実際的です。 https://stackoverflow.com/questions/5031614/the-jpa-hashcode-equals-dilemmaを参照してください。 – GKislin

10

これは現在、Hamcrest 2.0.0.0以降でサポートされています。

あなたは、例えば、これを達成するためにorg.hamcrest.comparator.ComparatorMatcherBuilderクラスを使用することができます。

ComparatorMatcherBuilder builder = ComparatorMatcherBuilder.comparedBy(equivalenceComparator); 
Assert.assertThat(eins, builder.comparesEqualTo(operand)); 
1

を私はhamcrest 1.3で同じ問題を抱えていたとマッチャーを書き込むことによってそれを解決し、ISEQUAL・マッチャーのコードに追従するが、 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; 
      } 
     })); 
    } 
} 
0

もう1つのオプションは、オブジェクトとiterablesにAspectJ framework custom comparison strategyを使用しています。

assertThat(frodo).usingComparator(raceComparator).isEqualTo(sam); 
assertThat(fellowshipOfTheRing).usingElementComparator(raceComparator).contains(sauron); 

Field by field comparisonsもあります。 isEqualToComparingOnlyGivenFieldsおよびisEqualToIgnoringGivenFieldsコンパレータ。

assertThat(frodo).isEqualToComparingOnlyGivenFields(sam, "race.name"); 
assertThat(frodo).isEqualToIgnoringGivenFields(sam, "name", "age"); 

ので、ほとんどの場合、あなたはあなたが[BaseMatcher](http://junit.org/javadoc/4.9/を拡張し、独自のマッチャーを書くしようとすることができるカスタム比較戦略