Skip to content

Instantly share code, notes, and snippets.

@Tzrlk
Created October 30, 2016 23:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tzrlk/4085e88b2bae3f5b046fff37ac93b905 to your computer and use it in GitHub Desktop.
Save Tzrlk/4085e88b2bae3f5b046fff37ac93b905 to your computer and use it in GitHub Desktop.
equatable
public interface Equatable<T> {
Equatator<T> getEquatator();
}
public interface Equatator<T> {
<L extends T, R extends T> boolean equatable(L left, R right);
}
import static org.mockito.Mockito.spy;
public class MethodArgument<T> implements Equatable<T> {
public static <T> MethodArgument<T> arg(T value, Equatator<T> equatator) {
return new MethodArgument<>(value, value.getClass(), equatator);
}
public static <T> MethodArgument<T> arg(T value, Class type, Equatator<T> equatator) {
return new MethodArgument<>(value, type, equatator);
}
public static Object[] getValues(MethodArgument<?>[] args) {
final Object[] objects = new Object[args.length];
for (int idx = 0; idx < args.length; idx++) {
objects[idx] = args[idx].toSpy();
}
return objects;
}
public static Class<?>[] getTypes(MethodArgument<?>[] args) {
final Class<?>[] types = new Class[args.length];
for (int idx = 0; idx < args.length; idx++) {
types[idx] = args[idx].type;
}
return types;
}
private final T value;
private final Class type;
private final Equatator<T> equatator;
private MethodArgument(T value, Class type, Equatator<T> equatator) {
this.value = value;
this.type = type;
this.equatator = equatator;
}
public T toSpy() {
return !type.isPrimitive()
? spy(value)
: value;
}
@Override
public Equatator<T> getEquatator() {
return equatator;
}
}
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static bravura.utils.abtesting.matchers.EquatableMatcher.equatableTo;
import static bravura.utils.abtesting.equatators.ExceptionEquatator.exceptionEquatator;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
public final class MethodEquatator {
public static <T> void check(String methodName, MethodArgument[] args, Equatator<T> sameAs)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Object[] args1 = MethodArgument.getValues(args).clone();
Method method1 = DateFunctions.class.getDeclaredMethod(methodName, MethodArgument.getTypes(args));
T result1 = null;
Exception error1 = null;
try {
result1 = (T) method1.invoke(null, args1);
} catch (InvocationTargetException | IllegalAccessException error) {
throw error;
} catch (Exception error) {
error1 = error;
}
Object[] args2 = MethodArgument.getValues(args).clone();
Method method2 = DateFunctionsOriginal.class.getDeclaredMethod(methodName, MethodArgument.getTypes(args));
T result2 = null;
Exception error2 = null;
try {
result2 = (T) method2.invoke(null, args2);
} catch (InvocationTargetException | IllegalAccessException error) {
throw error;
} catch (Exception error) {
error2 = error;
}
for (int idx = 0; idx < args.length; idx++) {
assertThat("Input arguments should have the same side-effects",
args1[idx], is(equatableTo(args2[idx], args[idx].getEquatator())));
}
assertThat("The results should be the same.",
result1, is(equatableTo(result2, sameAs)));
assertThat("The errors should be the same.",
error1, is(equatableTo(error2, exceptionEquatator)));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment