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

PowerMockito静态方法Mock:doReturn...When触发UnfinishedStubbingException问题

PowerMockito静态方法Stubbing异常原因解析

嘿,我来给你掰扯清楚这个问题!你遇到的UnfinishedStubbingException完全是因为PowerMockito中doReturn().when()针对静态方法的写法逻辑和实例方法不一样,咱们一步步拆解:

先看你的问题场景

你要模拟Cola类的静态drink()方法,用PowerMockito.when(Cola.drink()).thenReturn("Drinking")没问题,但换成PowerMockito.doReturn("Drinking").when(Cola.drink())就抛异常,对吧?

先把你的代码贴出来方便对照:

TestDrink.java

@RunWith(PowerMockRunner.class) 
@PrepareForTest({Drink.class,Cola.class}) 
public class TestDrink { 
    @Test 
    public void test() { 
        PowerMockito.mockStatic(Cola.class); 
        // 这个写法报错
        PowerMockito.doReturn("Drinking")
            .when(Cola.drink()); 
        System.out.println(Cola.drink()); 
    } 
}

Cola.java

public class Cola { 
    public static String drink() { 
        return "No drinking"; 
    } 
}

抛出的异常

org.mockito.exceptions.misusing.UnfinishedStubbingException: Unfinished stubbing detected here: 
-> at TestDrink.test(TestDrink.java:22)

E.g. thenReturn() may be missing. Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();

Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, you naughty developer!
 3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed
...(后面堆栈省略)

核心原因:两种Stubbing写法的逻辑差异

PowerMockito继承了Mockito的语法,但针对静态方法做了适配,这两个写法的本质区别在于调用时机和参数传递:

1. when(Cola.drink()).thenReturn("Drinking") 为什么正常?

这个写法是Mockito的**“存根前调用”**语法:

  • 首先调用Cola.drink(),但因为你已经用mockStatic(Cola.class)把Cola静态mock了,这个调用会被PowerMock拦截,标记为“需要存根的方法”
  • 然后调用thenReturn(),给这个被拦截的方法绑定返回值,整个流程是完整的,PowerMock能识别出这是一个完整的存根操作。

2. doReturn("Drinking").when(Cola.drink()) 为什么报错?

这个写法是Mockito的**“存根后调用”语法,原本是为了解决一些特殊场景(比如方法返回void、避免真实方法调用),但针对静态方法时,语法完全不一样**!

  • 你现在的写法里,when()的参数是Cola.drink()的调用结果,而不是“静态类的mock标记”
  • PowerMock看到的是:你先调用了doReturn(),然后调用了Cola.drink()(虽然被mock,但此时PowerMock不知道你是要存根这个方法,反而以为你是在存根过程中又执行了一个真实的mock方法调用,导致存根流程不完整)
  • 正确的静态方法doReturn()写法应该是:doReturn().when(Class.class),然后再跟方法调用,而不是把方法调用放进when()里!

正确的doReturn()静态方法存根写法

把你的代码改成下面这样就不会报错了:

PowerMockito.doReturn("Drinking")
    .when(Cola.class); // 这里传静态类本身,不是方法调用
Cola.drink(); // 这里才是要存根的方法调用

总结一下

针对PowerMockito静态方法的存根,两种写法的正确格式:

  • 常规写法(推荐):PowerMockito.when(Class.staticMethod()).thenReturn(xxx)
  • doReturn写法(特殊场景用):PowerMockito.doReturn(xxx).when(Class.class); Class.staticMethod();

别搞混参数就行,后者的when()里必须传类对象,不能传方法调用结果!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:05:50