Springboot+Mockito使用ReflectionTestUtils注入后方法被调用两次如何解决
JUnit5单元测试@Value字段注入后方法调用次数异常修复方案
核心问题原因
- 被测试类
MessageProcessor错误使用@Mock注解:@Mock会生成完全代理的虚拟对象,不会执行类内部的真实方法逻辑,且反射注入的字段不会作用于真实业务逻辑,是触发调用计数异常的核心原因。 - 辅助问题:
maxRetry字段未声明类型,@Value占位符语法错误(应为${}而非$()),注入值类型与字段类型不匹配(注入了字符串"5"而非整数)。
修复步骤
- 将测试类中
MessageProcessor的注解从@Mock替换为@InjectMocks:该注解会创建MessageProcessor的真实实例,且自动将测试类中声明的@Mock对象(如kafkaTemplate)注入到实例中。 - 修正业务类中
maxRetry的字段类型(建议为int),同时修改ReflectionTestUtils的注入值为整数类型5,避免类型转换异常。 - 补充触发业务逻辑的前置条件:给
handleMessage方法依赖的retry、msg变量赋值,保证retry > maxRetry的判断成立,正常触发sendMessage调用。
修复后代码示例
业务类MessageProcessor
public class MessageProcessor { // 修正@Value占位符语法,补充字段类型 @Value("${invoice.maxRetry}") private int maxRetry; // 补充依赖字段示例,根据实际业务调整 private int retry; private Object msg; private KafkaTemplate kafkaTemplate; protected void handleMessage() { if(retry > maxRetry) { kafkaTemplate.sendMessage(msg); } } // 省略setter、其他业务方法 }
测试类MessageProcessorTest
@ExtendWith(MockitoExtension.class) public class MessageProcessorTest { @Mock private KafkaTemplate kafkaTemplate; // 替换为@InjectMocks,创建真实的被测试实例 @InjectMocks private MessageProcessor messageProcessor; @Test public void testHandleMessage() { // 注入配置值,使用整数类型 ReflectionTestUtils.setField(messageProcessor, "maxRetry", 5); // 构造触发条件:retry=6 > 5 ReflectionTestUtils.setField(messageProcessor, "retry", 6); // 模拟msg对象 ReflectionTestUtils.setField(messageProcessor, "msg", new Object()); doNothing().when(kafkaTemplate).sendMessage(any()); messageProcessor.handleMessage(); // 显式指定调用次数,验证仅调用1次 verify(kafkaTemplate, times(1)).sendMessage(any()); } }
内容的提问来源于stack exchange,提问作者befocused47
相关产品推荐
相关产品推荐

