For several days I am using now Junit's Matchers feature. Everything is working OK but I am looking for a matcher which uses a comparator for comparing and which does not rely on the objects equals methodes.
I want to replace
Assert.assertThat(one, CoreMatchers.equalTo(two)
with something like (pseudocode)
Assert.assertThat(eins, CoreMatchers.equalTo(operand, new MyComparator())
Do you know whether there exists an easy out of the box solution? I did not find one in google and do not want to write one.
This is now supported in Hamcrest 2.0.0.0+.
You can use the org.hamcrest.comparator.ComparatorMatcherBuilder class to achieve this, for instance:
ComparatorMatcherBuilder builder = ComparatorMatcherBuilder.comparedBy(equivalenceComparator);
Assert.assertThat(eins, builder.comparesEqualTo(operand));
I had the same problem in hamcrest 1.3 and solved it by writing a matcher, that follows the code of the IsEqual-Matcher but uses a given Comparator instead of Object#equals().
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;
}
}));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With