JUnit5单元测试运行报ParameterResolutionException构造器参数解析错误
问题根因
- JUnit 5 默认不支持测试类构造器参数自动注入,你仅引入了
SpringExtension但未加载Spring上下文、未开启测试构造器注入能力,Spring无法识别构造参数对应的Bean,因此抛出ParameterResolutionException。 - 代码存在多处语法、配置不统一问题:
- 业务代码
CodeConfigBuilder中重复定义了两次validateRequestAndSetDefaults方法,第二次调用私有方法时错误传入类名而非参数变量 - 测试类中
PromoRequest拼写错误为PromonRequest,构造器属性赋值时混淆了参数名和类名 - 配置key不统一:
CodeConfigBuilder注入用的是promoConfig.prefix.length,PropertySourceResolver注入用的是promoGenerationConfig.prefix.length,会导致后续注入失败
- 业务代码
修复方案
方案1:启动Spring上下文做集成测试
适合需要验证配置加载、完整服务链路的场景:
- 先修复业务代码的语法、配置问题
- 删除
CodeConfigBuilder中重复的方法,修正方法调用逻辑:
@Component public class CodeConfigBuilder { @Value("${promoConfig.prefix.length}") private Integer prefixLength; public void validateRequestAndSetDefaults(PromoRequest promoRequest) { prefixAndPostFixControlAccordingToLength(promoRequest); } private void prefixAndPostFixControlAccordingToLength(PromoRequest promoRequest) { if (promoRequest.getPostfix() != null) { int lengthControl = prefixLength + promoRequest.getPostfix().length(); if (lengthControl >= promoRequest.getLength()) { throw new BadRequestException(Constant.ClientConstants.THE_SUM_OF_PREFIX_AND_POSTFIX_CAN_NOT_BE_GREATER_THAN_LENGHT); } } } }
- 统一配置key:将
PropertySourceResolver的注入注解改为@Value("${promoConfig.prefix.length}"),和yml配置保持一致
- 修正测试类注解和逻辑
@SpringBootTest // 加载Spring完整上下文 @TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL) // 开启测试类构造器自动注入(Spring Boot 2.2+支持) @ExtendWith(SpringExtension.class) class CodeConfigBuilderTest { private final PromoRequest promoRequest; private final PropertySourceResolver propertySourceResolver; private final PromoService promoService; private final Request request; // 修正拼写和属性赋值错误 public CodeConfigBuilderTest(PromoRequest promoGenerationRequest, PropertySourceResolver propertySourceResolver, PromoService promoService, Request request) { this.promoRequest = promoGenerationRequest; this.propertySourceResolver = propertySourceResolver; this.promoService = promoService; this.request = request; } @Test void prefixAndPostFixControlAccordingToLength() { // 先设置测试参数,避免空指针 promoRequest.setPostfix("test"); promoRequest.setLength(10); promoService.validateRequest(promoRequest); int lengthControl = propertySourceResolver.getPrefixLength() + promoRequest.getPostfix().length(); Assertions.assertTrue(lengthControl < promoRequest.getLength(), "前后缀长度之和不能大于指定总长度"); } }
方案2:轻量单元测试(无需启动Spring上下文)
适合仅测试业务逻辑、不需要验证配置加载的场景,执行效率更高:
@ExtendWith(MockitoExtension.class) class CodeConfigBuilderTest { @InjectMocks private CodeConfigBuilder codeConfigBuilder; @BeforeEach void setUp() { // 手动给@Value属性赋值,替代Spring配置注入 ReflectionTestUtils.setField(codeConfigBuilder, "prefixLength", 3); } @Test void testPrefixPostfixCheck() { PromoRequest request = new PromoRequest(); request.setPostfix("abc"); request.setLength(10); // 直接测试核心逻辑 Assertions.assertDoesNotThrow(() -> codeConfigBuilder.validateRequestAndSetDefaults(request)); // 测试异常场景 request.setLength(5); BadRequestException exception = Assertions.assertThrows(BadRequestException.class, () -> codeConfigBuilder.validateRequestAndSetDefaults(request)); Assertions.assertEquals(Constant.ClientConstants.THE_SUM_OF_PREFIX_AND_POSTFIX_CAN_NOT_BE_GREATER_THAN_LENGHT, exception.getMessage()); } }
内容的提问来源于stack exchange,提问作者mark whalf
相关产品推荐
相关产品推荐

