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

单元测试:如何验证被测void方法是否以正确参数调用了其他方法

解决方案

你之前测试失效的核心原因:Util.createEvent()是静态方法,普通Mockito的@Mock只能mock类的实例对象,无法拦截静态方法的调用,因此verify和ArgumentCaptor都不会生效。

下面提供两种可行方案:

方案1:使用Mockito静态mock能力(无需修改业务代码)

要求Mockito版本≥3.4.0,同时需要引入mockito-inline依赖(默认Mockito不支持静态mock,需要这个扩展)。

步骤1:引入依赖

如果是Maven项目,在pom.xml中添加:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>你的Mockito版本号</version>
    <scope>test</scope>
</dependency>

步骤2:编写单元测试示例

以下是验证code为SUCCESS场景下参数的测试用例:

import org.mockito.MockedStatic;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.times;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.anyMap;

// 测试类代码
@Test
void testOnMessageSuccessScenario() {
    // 1. 先模拟codeMagicThatDoesntConcernUsCurrently返回SUCCESS的逻辑,自行实现打桩逻辑
    // 2. 打开Util类的静态mock,用try-with-resources自动关闭
    try (MockedStatic<Util> mockedUtil = mockStatic(Util.class)) {
        // 3. 调用待测试的方法
        messageHandler.OnMessage();
        // 4. 验证静态方法调用的参数是否符合预期
        mockedUtil.verify(
            () -> Util.createEvent(
                anyString(), 
                eq(enumStatusObject.SUCCESS), 
                anyMap()
            ),
            times(1)
        );

        // 如果需要捕获参数做更复杂的校验,可以用ArgumentCaptor
        ArgumentCaptor<enumStatusObject> statusCaptor = ArgumentCaptor.forClass(enumStatusObject.class);
        mockedUtil.verify(
            () -> Util.createEvent(anyString(), statusCaptor.capture(), anyMap()),
            times(1)
        );
        Assert.assertEquals(enumStatusObject.SUCCESS, statusCaptor.getValue());
    }
}

对应不同分支场景只需修改打桩的code返回值,以及verify时匹配的枚举值即可:

  • code非SUCCESS场景:校验传入参数为enumStatusObject.ERROR
  • 异常场景:校验传入参数为enumStatusObject.EXCEPTION

方案2:优化业务代码消除静态依赖(更推荐,长期可维护性更高)

静态方法会导致强耦合、难测试,你可以通过依赖注入的方式改造代码,避免使用静态方法:

  1. 将Util类改为普通的Bean/组件,或者封装一层非静态的Wrapper类
  2. 在MessageHandler中通过构造函数/Setter注入Util实例
  3. 测试时直接用普通的@Mock注解mockUtil实例,你之前写的verify写法即可生效。

改造后的业务代码示例:

public class MessageHandler {
    // 注入Util实例,而非调用静态方法
    private final Util util;
    // 构造函数注入
    public MessageHandler(Util util) {
        this.util = util;
    }

    public void OnMessage() {
        // ... 原有逻辑
        if (!"SUCCESS".equals(code)) {
            // 调用实例方法而非静态方法
            util.createEvent(stringVariable, enumStatusObject.ERROR, mapPayload);
            log.info("oh no!");
            throw new RuntimeException();
        }
        // ... 其余逻辑
    }
}

改造后你之前写的verify(util, times(1)).createEvent(anyString(), eq(enumStatusObject.SUCCESS), anyMap());就可以正常生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 01:36:09