Hamcrest ist eine sehr nützliche Erweiterung der jUnit API um weitere Matcher.
Die ältere Version 1.3 hat aber keine isEqualTo
Methode, die einen Comparator aufnimmt, um die Objekte anders als mit Object#equals()
zu vergleichen.
Also habe ich den vorhandenen IsEqual-Matcher als Vorlage genommen und daraus den IsEqualWithComparator
erstellt.
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}.
*/
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;
}
}));
}
}