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

如何在JUnit Jupiter ExecutionCondition中注入Spring Bean并解决实例化异常

解决JUnit 5 @ExtendWith结合Spring Bean的问题

问题根源

你遇到的NoSuchMethodException是因为JUnit 5的Extension(比如你实现的ExecutionCondition)如果直接通过@ExtendWith指定类,JUnit会尝试用无参构造函数实例化它,但你的PlatformExecutionCondition用了@RequiredArgsConstructor,没有生成无参构造;更关键的是,JUnit的实例化流程不会走Spring容器,所以你依赖的EmulatorConfigProperties和PlatformAnnotationManager根本没法注入。

正确实现方式

要让自定义Condition结合Spring使用,核心是让Extension能获取到Spring容器中的Bean,而不是让JUnit直接实例化你的Condition类。

方案1:通过SpringExtension委托调用Spring管理的Condition

  1. 调整你的PlatformExecutionCondition:保留@Component和@RequiredArgsConstructor,确保它是Spring容器管理的Bean,正常实现ExecutionCondition接口:
@Component
@RequiredArgsConstructor
public class PlatformExecutionCondition implements ExecutionCondition {
    private final EmulatorConfigProperties emulatorConfig;
    private final PlatformAnnotationManager platformAnnotationManager;

    @Override
    public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
        // 你的原有逻辑实现
        // ...
    }
}
  1. 创建Spring感知的代理Extension:这个Extension负责从Spring容器中取出你的Condition实例,然后委托执行逻辑:
public class SpringPlatformExtension implements ExecutionCondition {
    @Override
    public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
        // 通过SpringExtension获取当前测试的Spring上下文
        ApplicationContext ctx = SpringExtension.getApplicationContext(context);
        // 从容器中取出你的Condition Bean
        PlatformExecutionCondition condition = ctx.getBean(PlatformExecutionCondition.class);
        // 委托执行原有逻辑
        return condition.evaluateExecutionCondition(context);
    }
}
  1. 配置测试类:测试类上使用@SpringJUnitConfig(Spring Boot项目用@SpringBootTest)启动Spring容器,同时用@ExtendWith指定代理的Extension:
@SpringJUnitConfig(classes = {你的配置类.class})
@ExtendWith(SpringPlatformExtension.class)
@Platform // 你的自定义注解
public class YourTest {
    // 测试方法
}

方案2:在Condition内部直接获取Spring上下文(简化版)

如果不想写代理类,可以直接在PlatformExecutionCondition中通过SpringExtension获取上下文,去掉构造注入,改为从容器中取Bean:

public class PlatformExecutionCondition implements ExecutionCondition {
    @Override
    public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
        ApplicationContext ctx = SpringExtension.getApplicationContext(context);
        EmulatorConfigProperties emulatorConfig = ctx.getBean(EmulatorConfigProperties.class);
        PlatformAnnotationManager platformAnnotationManager = ctx.getBean(PlatformAnnotationManager.class);
        
        // 你的原有逻辑实现
        // ...
    }
}

然后测试类上同时加@SpringJUnitConfig(或@SpringBootTest)和@ExtendWith(PlatformExecutionCondition.class)即可。这种方式不需要把Condition注册为Spring Bean,但逻辑上把依赖获取嵌入到了Condition方法中。

关键注意点

  • 必须用@SpringJUnitConfig或@SpringBootTest来启动Spring容器,这两个注解已经包含了@ExtendWith(SpringExtension.class),是Spring和JUnit整合的基础。
  • 不要让JUnit直接实例化依赖Spring Bean的Extension,必须通过Spring容器获取实例或依赖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 06:47:09