You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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;
    }
}

说明

  1. 通过context.getRequiredTestClass()拿到实际执行测试的子类(比如UserEntityTest extends BaseEntityTest<UserEntity>)
  2. 解析该子类的泛型父类信息,提取出ENTITY对应的实际Class类型
  3. 兼容了多层抽象类继承的场景,确保能正确定位到最上层的实际泛型参数

内容的提问来源于stack exchange,提问作者Jin Kwon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 18:42:39