In two earlier blog posts I commented on parametrized junit tests. This blog post will complement these post with an example of a piece of code.
Because all the important points are made in the other posts I will only present the Junit runner I created. A Maven project demonstrating this technique can be found code at my minimal examples repository
Without further ado: the Junit runner.
package org.junit.runners;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.Parameterized.Parameters;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import org.junit.runners.model.TestClass;
public class ParameterizedWithBuilder extends Suite
{
private class TestClassRunnerForParametersWithBuilder extends BlockJUnit4ClassRunner
{
private final int fParameterSetNumber;
private final List<Object> fParameterList;
TestClassRunnerForParametersWithBuilder(Class<?> type, List<Object> parametersList, int i)
throws InitializationError
{
super(type);
fParameterList = parametersList;
fParameterSetNumber = i;
}
@Override
public Object createTest() throws Exception
{
return getTestClass().getOnlyConstructor().newInstance(computeParams());
}
private Object computeParams() throws Exception
{
try
{
return fParameterList.get(fParameterSetNumber);
}
catch (ClassCastException e)
{
throw new Exception(String.format("%s.%s() must return a Collection of objects.", getTestClass()
.getName(), getParametersMethod(getTestClass()).getName()));
}
}
@Override
protected String getName()
{
return String.format("[%s]", fParameterSetNumber);
}
@Override
protected String testName(final FrameworkMethod method)
{
return String.format("%s[%s]", method.getName(), fParameterSetNumber);
}
@Override
protected void validateConstructor(List<Throwable> errors)
{
validateOnlyOneConstructor(errors);
}
@Override
protected Statement classBlock(RunNotifier notifier)
{
return childrenInvoker(notifier);
}
}
private List<Runner> runners = new ArrayList<Runner>();
public ParameterizedWithBuilder(Class<?> klass) throws Throwable
{
super(klass, Collections.<Runner> emptyList());
List<Object> parametersList = getParametersList(getTestClass());
for (int i = 0; i < parametersList.size(); i++)
runners.add(new TestClassRunnerForParametersWithBuilder(getTestClass().getJavaClass(), parametersList, i));
}
@Override
protected List<Runner> getChildren()
{
return runners;
}
@SuppressWarnings("unchecked")
private List<Object> getParametersList(TestClass testClass) throws Throwable
{
return (List<Object>) getParametersMethod(testClass).invokeExplosively(null);
}
private FrameworkMethod getParametersMethod(TestClass testClass) throws Exception
{
List<FrameworkMethod> methods = testClass.getAnnotatedMethods(Parameters.class);
for (FrameworkMethod each : methods)
{
int modifiers = each.getMethod().getModifiers();
if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))
return each;
}
throw new Exception("No public static parameters method on class " + testClass.getName());
}
}