Skip to content

Instantly share code, notes, and snippets.

@arnehormann
Last active December 29, 2015 13:39
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 arnehormann/7678580 to your computer and use it in GitHub Desktop.
Save arnehormann/7678580 to your computer and use it in GitHub Desktop.
some reflection magic to help writing table based tests
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
public final class TestHelper {
public static void test(Object[][] tests, Object target, String methodName, Class<?>...argsTypes) throws Exception {
Class<?> baseClass;
if (target instanceof Class) {
// static method
baseClass = (Class<?>) target;
target = null;
} else {
baseClass = target.getClass();
}
Method method = baseClass.getDeclaredMethod(methodName, argsTypes);
if (!method.isAccessible()) {
method.setAccessible(true);
}
// iterate over test data arrays (arguments for tested method followed by expected value)
// and if the expected value is a real value check and compare the result.
// If it's an Exception, catch it and compare class and message with expected Exception.
// This does not account for methods returning Exceptions.
try {
Object[] args = new Object[method.getGenericParameterTypes().length];
for (int i = 0; i < tests.length; i++) {
Object[] test = tests[i];
final String message = "case " + i + ": " + Arrays.toString(test);
// expected is always the last value
final Object expected = test[test.length - 1];
System.arraycopy(test, 0, args, 0, test.length - 1);
try {
final Object actual = method.invoke(null, args);
if (actual == null || expected.getClass() != actual.getClass()) {
throw new RuntimeException("actual and expected values do not match in " + message);
}
// compare with expected int, Date, String, ...
assertEquals(message, expected, actual);
continue;
} catch (InvocationTargetException e) {
if (e.getTargetException().getClass() == expected.getClass()) {
// compare with expected Exception by class and message
assertEquals(message,
((Exception) expected).getMessage(),
e.getTargetException().getMessage()
);
continue;
}
// detailed exception message mentioning failed test case
throw new RuntimeException(message, e);
}
}
} catch (IllegalAccessException e) {
fail(e.getMessage());
}
}
}
@arnehormann
Copy link
Author

And here is a helper method to mark unreachable code and get parameter information:

    // helper method for exceptions in unreachable locations
    private static RuntimeException unreachable(Throwable t, Object... args) {
        StringBuilder builder = new StringBuilder("PANIC for (");
        if (args.length > 0) {
            builder.append(args[0]);
            for (int i = 0; i < args.length; i++) {
                builder.append(", ").append(args[i]);
            }
        }
        builder.append("). Contact the maintainer");
        if (t != null) {
            return new RuntimeException(builder.toString(), t);
        }
        return new RuntimeException(builder.toString());
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment