Junit5自定义ArgumentsSource用于加载json数据作为ParameterizedTest的参数
实现方案
- 实现一个自定义注解
MyJsonSource
- 实现对应的
JsonFileArgumentsProvider
实现代码
package local.my.demo_jdk.t;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.*;
import org.junit.jupiter.params.support.ParameterDeclaration;
import org.junit.jupiter.params.support.ParameterDeclarations;
import java.lang.annotation.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@ArgumentsSource(MyJsonSource.JsonFileArgumentsProvider.class)
public @interface MyJsonSource {
String[] value();
class JsonFileArgumentsProvider extends AnnotationBasedArgumentsProvider {
@Override
protected Stream provideArguments(ParameterDeclarations parameters, ExtensionContext context,
MyJsonSource source) {
var types = parameters.getAll().stream().map(ParameterDeclaration::getParameterType).toList();
List argumentsList = new ArrayList<>();
if (source.value() != null) {
for (String sourceStr : source.value()) {
if (sourceStr == null || (sourceStr = sourceStr.trim()).isEmpty()) {
continue;
}
argumentsList.add(read(sourceStr, types));
}
}
return argumentsList.stream();
}
private static String load(String sourceStr) {
if (sourceStr.endsWith(".json") || sourceStr.endsWith(".json5") || sourceStr.endsWith(".jsonl")) {
sourceStr = ResourceUtil.readStr(sourceStr, StandardCharsets.UTF_8);
}
return sourceStr == null ? null : sourceStr.trim();
}
private static Arguments read(String sourceStr, List> types) {
String value = load(sourceStr);
if (value.startsWith("{")) {
var j = JSONUtil.parse(value);
return Arguments.of(j.toBean(types.getFirst()));
} else if (value.startsWith("[")) {
if (types.size() <= 1) {
if (types.getFirst().isAssignableFrom(List.class))
return Arguments.of(JSONUtil.toList(value, types.getFirst()));
else
return Arguments.of(((JSON) JSONUtil.parseArray(value).get(0)).toBean(types.getFirst()));
} else {
var arr = JSONUtil.parseArray(value);
Object[] objs = new Object[types.size()];
for (int i = 0; i < Math.min(types.size(), arr.size()); i++) {
JSONUtil.toBean((JSON) arr.get(i), types.get(i), true);
}
return Arguments.of(objs);
}
} else
throw new RuntimeException("不支持的类型:"+sourceStr);
}
}
}
测试
import org.junit.jupiter.params.ParameterizedTest
class MyTest {
@ParameterizedTest
@MyJsonSource(["""
{"a":1}""",
//假设resources/test.json文件内容为{"a":2}
"test.json"])
void test2(Map s) {
println s
}
}
/*
运行测试将输出
> Task :testClasses
[a:1]
[a:2]
> Task :test
Gv1Test > test2(Map) > [1] {a=1} PASSED
Gv1Test > test2(Map) > [2] {a=2} PASSED
*/