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

JUnit5扩展注册时如何注入依赖并传入测试类初始化参数

问题原因

原来的实现报错是因为:JUnit 初始化@RegisterExtension标注的扩展实例的时机,早于Spring测试框架对测试类字段的依赖注入流程,此时dataSource还未被赋值为null,自然无法正常运行。

方案1:Supplier延迟加载(最推荐,完全框架无关)

该方案无需绑定任何框架,仅依赖Java 8+的Supplier特性,适配所有测试场景,不管你用Spring还是其他依赖注入框架,甚至是手动给测试类字段赋值都可以使用,不强制依赖@Autowired。

扩展修改:

@RequiredArgsConstructor
public class FakeExtension implements BeforeEachCallback {
    // 用Supplier包装参数,延迟到实际执行逻辑时再获取值
    private final Supplier<DataSource> dataSourceSupplier;

    @Override
    public void beforeEach(ExtensionContext context) throws Exception {
        // 此时测试类的字段已经完成初始化/注入,可以拿到有效值
        DataSource dataSource = dataSourceSupplier.get();
        System.out.println("Do something with " + dataSource);
    }
}

测试类使用:

@SpringBootTest
public class FakeTest {
    @Autowired
    DataSource dataSource;

    // 传入lambda返回当前实例的dataSource字段
    @RegisterExtension
    FakeExtension ext = new FakeExtension(() -> this.dataSource);

    @Test
    void test() {
        System.out.println("Run test");
    }
}

方案2:扩展内反射获取测试类字段(测试类无侵入)

如果不想修改原有扩展的入参定义,或者不想在每个测试类里编写Supplier逻辑,可以选择在扩展内部通过JUnit上下文拿到测试类实例,反射读取对应字段,同样完全不依赖Spring框架。

扩展实现:

public class FakeExtension implements BeforeEachCallback {
    @Override
    public void beforeEach(ExtensionContext context) throws Exception {
        // 获取当前测试类实例
        Object testInstance = context.getRequiredTestInstance();
        // 反射读取字段,可自定义注解标记目标字段提升通用性
        Field dataSourceField = Arrays.stream(testInstance.getClass().getDeclaredFields())
                .filter(f -> f.getType() == DataSource.class)
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("测试类未定义DataSource类型字段"));
        dataSourceField.setAccessible(true);
        DataSource dataSource = (DataSource) dataSourceField.get(testInstance);
        System.out.println("Do something with " + dataSource);
    }
}

测试类使用:

直接添加扩展注解即可,无需额外编码:

@SpringBootTest
@ExtendWith(FakeExtension.class)
public class FakeTest {
    @Autowired
    DataSource dataSource;

    @Test
    void test() {
        System.out.println("Run test");
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 17:57:01