如何用Mockito验证方法是否传入Msg.SAVE或Msg.UPDATE参数调用
验证Mockito中方法是否以指定参数之一被调用
业务代码片段
先给出对应场景的简化业务代码参考:
// Msg枚举类 public enum Msg { SAVE, UPDATE } // 消息发送接口 public interface SendMessageInTopic { void sendMessage(Msg msg); } // 核心业务类 @Service public class CustomerService { private final SendMessageInTopic sendMessageInTopic; private final CustomerRepository customerRepository; public CustomerService(SendMessageInTopic sendMessageInTopic, CustomerRepository customerRepository) { this.sendMessageInTopic = sendMessageInTopic; this.customerRepository = customerRepository; } public void saveCustomer(Customer customer) { boolean exists = customerRepository.existsById(customer.getId()); if (exists) { sendMessageInTopic.sendMessage(Msg.UPDATE); } else { sendMessageInTopic.sendMessage(Msg.SAVE); } customerRepository.save(customer); } }
测试实现方案
1. 拆分独立测试用例(推荐)
最清晰的做法是针对新增和更新两个场景分别写测试,各自验证对应的参数调用:
@ExtendWith(MockitoExtension.class) public class CustomerServiceTest { @Mock private SendMessageInTopic sendMessageInTopic; @Mock private CustomerRepository customerRepository; @InjectMocks private CustomerService customerService; // 验证新增客户时发送SAVE消息 @Test void saveCustomer_WhenNew_SendsSaveMsg() { // 给定:客户不存在 Customer newCustomer = new Customer(1L, "Alice"); when(customerRepository.existsById(1L)).thenReturn(false); // 执行 customerService.saveCustomer(newCustomer); // 验证 verify(sendMessageInTopic).sendMessage(Msg.SAVE); } // 验证更新客户时发送UPDATE消息 @Test void saveCustomer_WhenExisting_SendsUpdateMsg() { // 给定:客户已存在 Customer existingCustomer = new Customer(1L, "Alice"); when(customerRepository.existsById(1L)).thenReturn(true); // 执行 customerService.saveCustomer(existingCustomer); // 验证 verify(sendMessageInTopic).sendMessage(Msg.UPDATE); } }
2. 单个测试中验证参数为两者之一(可选)
如果一定要在单个测试里覆盖两种参数情况,可使用Mockito的argThat匹配器:
@Test void saveCustomer_SendsEitherSaveOrUpdateMsg() { Customer testCustomer = new Customer(1L, "Alice"); // 测试新增场景 when(customerRepository.existsById(1L)).thenReturn(false); customerService.saveCustomer(testCustomer); verify(sendMessageInTopic).sendMessage(argThat(msg -> msg == Msg.SAVE || msg == Msg.UPDATE)); // 重置mock调用记录,测试更新场景 reset(sendMessageInTopic); when(customerRepository.existsById(1L)).thenReturn(true); customerService.saveCustomer(testCustomer); verify(sendMessageInTopic).sendMessage(argThat(msg -> msg == Msg.SAVE || msg == Msg.UPDATE)); }
关键提示
- 优先选择拆分测试用例的方式:每个测试只验证单一场景,可读性更强,测试失败时能快速定位问题。
- 使用
argThat时,lambda逻辑要尽量简洁,避免引入复杂判断导致测试逻辑混乱。 - 重置mock调用记录时用
reset()方法,但尽量避免在单个测试中多次执行被测方法,除非业务场景需要。
内容的提问来源于stack exchange,提问作者obela06
相关产品推荐
相关产品推荐

