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

如何Mock静态非void方法使其两次调用表现不同?

Mock静态方法实现首次抛异常、二次返回指定值及调用验证

我需要Mock一个静态方法,让它第一次调用时抛出异常,第二次调用时返回指定值。我知道单独Mock抛异常或返回值的方法,但不知道怎么让它在连续两次调用中表现不同。

同时,我该如何在单个测试中验证对Mock静态方法的两次连续调用?能不能在一个MockedStatic代码块里实现,还是需要为每次调用分别用不同的MockedStatic代码块?以下是示例代码:

/** 包含待Mock静态方法的工具类 */
public final class VariableUtil {   
            
  // 待Mock的静态方法
  public static JsonValue createJsonVariable(Object variableValue) throws Exception{…..}
}
    
/** JsonValue接口 */
public interface JsonValue extends PrimitiveValue<String> {
}

/** 使用VariableUtil的业务类 */
public class SomeClass {

    // 调用两次静态方法的业务方法
    public void someMethod() {
    
        try {
            // 第一次调用静态方法,预期抛出异常
            VariableUtil.createJsonVariable(
                Collections.singletonList(someObject));

        } catch(Exception ex) {
            // 捕获异常后第二次调用静态方法,预期返回Mock值
            JsonValue someJsonValue = VariableUtil.createJsonVariable(
                Collections.singletonList(someObject));
        }
    }
}

/** JUnit测试类 */
@Test
public void testCreateVariable() {

    // 下面的写法不生效,怎么Mock才能让第一次调用抛异常、第二次返回值?
 
    try (final MockedStatic<VariableUtil> variableUtilMock = 
        // Mock抛出异常
        mockStatic(VariableUtil.class)) {
          variableUtilMock.when(() -> VariableUtil.createJsonVariable(processingFailureErrorMessage))
                .thenThrow(new Exception());
        
        // Mock返回值
        variableUtilMock.when(() -> VariableUtil.createJsonVariable(processingFailureErrorMessage))
                .thenReturn("someJsonValue");
            
            SomeClass someObject = new SomeClass();
            someObject.someMethod();
        }
}

解决方案

1. 实现连续调用的不同行为

你完全可以在同一个MockedStatic代码块里实现需求,无需拆分。Mockito提供了两种简单方式:

方式一:链式指定调用顺序

直接通过thenThrow().thenReturn()的链式调用,按调用顺序定义行为:

@Test
public void testCreateVariable() {
    // 提前Mock一个JsonValue实例(因为JsonValue是接口,需要Mock实现)
    JsonValue mockJsonValue = Mockito.mock(JsonValue.class);

    try (final MockedStatic<VariableUtil> variableUtilMock = Mockito.mockStatic(VariableUtil.class)) {
        // 第一次调用抛异常,第二次返回Mock实例
        variableUtilMock.when(() -> VariableUtil.createJsonVariable(processingFailureErrorMessage))
                .thenThrow(new Exception())
                .thenReturn(mockJsonValue);

        SomeClass someClass = new SomeClass();
        someClass.someMethod();

        // 验证静态方法被调用了两次
        variableUtilMock.verify(() -> VariableUtil.createJsonVariable(processingFailureErrorMessage), Mockito.times(2));
    }
}

方式二:自定义Answer逻辑(适用于复杂场景)

如果需要更灵活的调用控制,可以用thenAnswer结合计数器实现:

@Test
public void testCreateVariableWithCustomAnswer() {
    AtomicInteger callCounter = new AtomicInteger(0);
    JsonValue mockJsonValue = Mockito.mock(JsonValue.class);

    try (final MockedStatic<VariableUtil> variableUtilMock = Mockito.mockStatic(VariableUtil.class)) {
        variableUtilMock.when(() -> VariableUtil.createJsonVariable(processingFailureErrorMessage))
                .thenAnswer(invocation -> {
                    int currentCall = callCounter.incrementAndGet();
                    if (currentCall == 1) {
                        throw new Exception();
                    } else {
                        return mockJsonValue;
                    }
                });

        SomeClass someClass = new SomeClass();
        someClass.someMethod();

        // 验证调用次数
        variableUtilMock.verify(() -> VariableUtil.createJsonVariable(processingFailureErrorMessage), Mockito.times(2));
    }
}

2. 关键注意事项

  • 无需拆分MockedStatic块:同一个try-with-resources声明的MockedStatic会覆盖整个测试方法内的静态方法调用,两次调用都在同一Mock控制下。
  • 参数匹配一致性:when和verify中的参数要完全匹配(比如processingFailureErrorMessage要和业务方法中传入的参数一致),如果需要放宽匹配条件,可以用Mockito.any()等匹配器。
  • Mock接口实例:因为JsonValue是接口,不能直接返回字符串,需要用Mockito.mock(JsonValue.class)创建Mock实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 17:25:09