如何在BaseEntityArgumentsProvider中获取泛型ENTITY的实际类型?
解决BaseEntityArgumentsProvider中获取ENTITY实际类型的问题
首先,你定义的抽象实体类:
abstract class BaseEntity<SELF extends BaseEntity<SELF>> { }
抽象测试类:
abstract class BaseEntityTest<ENTITY extends BaseEntity<ENTITY>> { @ArgumentsSource(BaseEntityTestArgumentsProvider.class) @ParameterizedTest void _NotBlank_ToString(final ENTITY entityInstance) { } protected final Class<ENTITY> entityClass; }
当前的参数提供类:
public class BaseEntityArgumentsProvider implements ArgumentsProvider { @Override public Stream<? extends Arguments> provideArguments(final ParameterDeclarations parameters, final ExtensionContext context) throws Exception { final var firstParameterType = parameters.getFirst().map(ParameterDeclaration::getParameterType).orElse(null); if (firstParameterType == null) { return Stream.empty(); } if (!BaseEntity.class.isAssignableFrom(firstParameterType)) { return Stream.empty(); } return BaseEntityTest_Utils.getEntityInstanceStream( firstParameterType.asSubclass(BaseEntity.class) ).map(Arguments::of); } }
问题原因
Java泛型存在类型擦除机制,直接通过ParameterDeclaration获取的参数类型会被擦除为BaseEntity.class,无法拿到ENTITY对应的实际子类类型。
解决方案
需要从ExtensionContext中获取当前运行的测试子类,解析该类继承的BaseEntityTest泛型参数,从而提取ENTITY的实际类型:
修改后的BaseEntityArgumentsProvider代码如下:
public class BaseEntityArgumentsProvider implements ArgumentsProvider { @Override public Stream<? extends Arguments> provideArguments(final ParameterDeclarations parameters, final ExtensionContext context) throws Exception { // 获取当前执行测试的类 Class<?> testClass = context.getRequiredTestClass(); // 解析出ENTITY对应的实际类型 Class<? extends BaseEntity<?>> entityClass = resolveEntityClass(testClass); if (entityClass == null) { return Stream.empty(); } return BaseEntityTest_Utils.getEntityInstanceStream(entityClass) .map(Arguments::of); } @SuppressWarnings("unchecked") private Class<? extends BaseEntity<?>> resolveEntityClass(Class<?> testClass) { Type genericSuperclass = testClass.getGenericSuperclass(); // 判断父类是否为带泛型参数的类型 if (genericSuperclass instanceof ParameterizedType parameterizedType) { // 取第一个泛型参数(对应ENTITY) Type actualType = parameterizedType.getActualTypeArguments()[0]; if (actualType instanceof Class<?> clazz) { return (Class<? extends BaseEntity<?>>) clazz; } // 处理嵌套泛型的特殊情况 else if (actualType instanceof ParameterizedType nestedType) { Type rawType = nestedType.getRawType(); if (rawType instanceof Class<?> clazz) { return (Class<? extends BaseEntity<?>>) clazz; } } } // 处理多层抽象类继承的情况,递归向上查找 if (Modifier.isAbstract(testClass.getModifiers())) { Class<?> superclass = testClass.getSuperclass(); if (superclass != null && superclass != Object.class) { return resolveEntityClass(superclass); } } return null; } }
说明
- 通过
context.getRequiredTestClass()拿到实际执行测试的子类(比如UserEntityTest extends BaseEntityTest<UserEntity>) - 解析该子类的泛型父类信息,提取出
ENTITY对应的实际Class类型 - 兼容了多层抽象类继承的场景,确保能正确定位到最上层的实际泛型参数
内容的提问来源于stack exchange,提问作者Jin Kwon
相关产品推荐
相关产品推荐

