我必须使用具有注释@Parameterized.Parameters(name = "{0}")的集合中的自动连接参数的JUnit测试,该集合中已经有很多测试。我想添加一个参数,但就像大多数程序员一样,我是一个非常懒惰的人,所以我想引入一个可选的参数,这可能吗?
@Parameterized.Parameter()
importantParameter;
@Parameterized.Parameter(1)
evenMoreImportantParameter;
@Parameterized.Parameter(2)
businessHandshakeBusinessYes;
@Parameterized.Parameter(3)
meBeingLazyOptionalParameter;
@Parameterized.Parameters(name = "{0}")
public static Collection<Object[]> data() {
Collection<Object[]> params = new ArrayList<>();
params.add(new Object[]{ "wow", "very", "impressive"});
params.add(new Object[]{ "wow", "much", "beautiful"});
// Where I want to be lazy
params.add(new Object[]{ "this", "is", "sooooo", "better"});
return params;
}在前面显示的情况下,只有最后一次测试才会成功,前两次测试将生成以下错误消息
java.lang.Exception: Wrong number of parameters and @Parameter fields. @Parameter fields counted: 4, available parameters: 3.发布于 2021-03-29 01:10:27
快速浏览一下Parameterized.class和BlockJUnit4ClassRunnerWithParameters.class的源代码就会发现,不可能指定可选参数。
就我个人而言,我会保持所有参数的大小不变,但您始终可以创建单元运行器,复制Parameterized.class并使用null将数组填充到最大大小。
下面是一个执行填充的Parameterized运行器的示例(在JUnit中是原始运行器的副本,但使用了采用allParameters的私有方法):
public class Parameterized extends Suite {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public static @interface Parameters {
String name() default "{index}";
// The max number of parameters
int size();
}
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Target(ElementType.TYPE)
public @interface UseParametersRunnerFactory {
Class<? extends ParametersRunnerFactory> value() default BlockJUnit4ClassRunnerWithParametersFactory.class;
}
private static final ParametersRunnerFactory DEFAULT_FACTORY = new BlockJUnit4ClassRunnerWithParametersFactory();
private static final List<Runner> NO_RUNNERS = Collections.<Runner>emptyList();
private final List<Runner> runners;
private final int size;
public Parameterized(Class<?> klass) throws Throwable {
super(klass, NO_RUNNERS);
ParametersRunnerFactory runnerFactory = getParametersRunnerFactory( klass);
Parameters parameters = getParametersMethod().getAnnotation( Parameters.class);
size = parameters.size();
runners = Collections.unmodifiableList(createRunnersForParameters( allParameters(), parameters.name(), runnerFactory));
}
private ParametersRunnerFactory getParametersRunnerFactory(Class<?> klass)
throws InstantiationException, IllegalAccessException {
UseParametersRunnerFactory annotation = klass
.getAnnotation(UseParametersRunnerFactory.class);
if (annotation == null) {
return DEFAULT_FACTORY;
} else {
Class<? extends ParametersRunnerFactory> factoryClass = annotation.value();
return factoryClass.newInstance();
}
}
@Override
protected List<Runner> getChildren() {
return runners;
}
private TestWithParameters createTestWithNotNormalizedParameters(String pattern, int index, Object parametersOrSingleParameter) {
Object[] parameters= (parametersOrSingleParameter instanceof Object[])
? (Object[]) parametersOrSingleParameter
: new Object[] { parametersOrSingleParameter };
return createTestWithParameters(getTestClass(), pattern, index, parameters);
}
private Iterable<Object> allParameters() throws Throwable {
Object parameters = getParametersMethod().invokeExplosively(null);
if (parameters instanceof Iterable) {
return pad((Iterable<Object>) parameters);
} else if (parameters instanceof Object[]) {
return pad(Arrays.asList((Object[]) parameters));
} else {
throw parametersMethodReturnedWrongType();
}
}
private Iterable<Object> pad(Iterable<Object> parameters) {
List<Object> padded = new ArrayList<>();
for ( Object parameter : parameters ) {
Object[] paddedParams = new Object[size];
Object[] current = (Object[]) parameter;
System.arraycopy( current, 0, paddedParams, 0, current.length );
padded.add( paddedParams );
}
return padded;
}
private FrameworkMethod getParametersMethod() throws Exception {
List<FrameworkMethod> methods = getTestClass().getAnnotatedMethods(
Parameters.class);
for (FrameworkMethod each : methods) {
if (each.isStatic() && each.isPublic()) {
return each;
}
}
throw new Exception("No public static parameters method on class " + getTestClass().getName());
}
private List<Runner> createRunnersForParameters(
Iterable<Object> allParameters, String namePattern,
ParametersRunnerFactory runnerFactory)
throws InitializationError,
Exception {
try {
List<TestWithParameters> tests = createTestsForParameters(
allParameters, namePattern);
List<Runner> runners = new ArrayList<Runner>();
for (TestWithParameters test : tests) {
runners.add(runnerFactory
.createRunnerForTestWithParameters(test));
}
return runners;
} catch (ClassCastException e) {
throw parametersMethodReturnedWrongType();
}
}
private List<TestWithParameters> createTestsForParameters(
Iterable<Object> allParameters, String namePattern)
throws Exception {
int i = 0;
List<TestWithParameters> children = new ArrayList<TestWithParameters>();
for (Object parametersOfSingleTest : allParameters) {
children.add(createTestWithNotNormalizedParameters(namePattern,
i++, parametersOfSingleTest));
}
return children;
}
private Exception parametersMethodReturnedWrongType() throws Exception {
String className = getTestClass().getName();
String methodName = getParametersMethod().getName();
String message = MessageFormat.format( "{0}.{1}() must return an Iterable of arrays.", className, methodName);
return new Exception(message);
}
private static TestWithParameters createTestWithParameters(
TestClass testClass, String pattern, int index, Object[] parameters) {
String finalPattern = pattern.replaceAll("\\{index\\}", Integer.toString(index));
String name = MessageFormat.format(finalPattern, parameters);
return new TestWithParameters("[" + name + "]", testClass, Arrays.asList(parameters));
}
}https://stackoverflow.com/questions/66843781
复制相似问题