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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 15:37:13