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

使用Mockito/JUnit测试含泛型的final void方法触发异常问题

问题:Mockito无法mock带泛型的final void方法

我尝试用Mockito和JUnit测试一个包含泛型参数的void方法,期望通过doNothing()模拟该方法,但运行测试时触发异常;而无泛型参数的error方法却能正常运行。两者的差异在于success方法被定义为final,error方法则不是。

抛出的异常信息

You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
when(mock.get(anyInt())).thenReturn(null);
doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
verify(mock).someMethod(contains("foo"))

Also, this error might show up because you use argument matchers with
methods that cannot be mocked. Following methods cannot be
stubbed/verified: final/private/equals()/hashCode(). Mocking methods
declared on non-public parent classes is not supported.

相关代码

待测试类 GreenWork.java

public class GreenWork {
       @Autowired 
       Service service;
       public void getDataResponses() {
    
        ResponseEntity<DataDTO> responseEntity = restTemplate.exchange(
                        settings.getUrk(),
                        HttpMethod.GET,
                        null,
                        DataDTO.class);
        
        if (responseEntity.getStatusCode().is4xxClientError()) {
            ErrorData errorData = new ErrorData();
            errorData.setMessage("error loading");
            service.error("corId", errorData, "otherId");
        } else {
            service.success("corId", responseEntity.getBody(), "otherId");
        }
   }
}

服务类 Service.java

public final void success(
        final String corId,
        final T t, // Generic class
        final String otherud)
        throws Exception {
    
    ......
    restTemplate.exchange(
        "url"),
        entity,
        Void.class);
}


public void error(
        final String corId,
        final ErrorData errorData,
        final String otherud)
        throws Exception {
    
    ......
    restTemplate.exchange(
        "url"),
        entity,
        Void.class);
}

JUnit测试代码

@InjectMocks
private GreenWork greenWork;

@Test
public void shoulSuccessCallbak() {
    doNothing().when(service).success(anyString(), any(), anyString());  // 触发Exception 1异常
    doNothing().when(service).success(anyString(), any(GrayDTO.class), anyString()); // 同样触发异常
    doNothing().when(service).error("corId", any(ErrorData.class), "xId");  // 无异常,正常运行
    greenWork.getDataResponses();
}

解决方案

问题核心不是泛型,而是Mockito默认不支持mock final方法,异常提示里已经明确说明:final方法无法被stub/verify。success方法是final修饰的,所以不管用不用泛型参数匹配,都会触发异常;而error方法不是final,因此能正常mock。

解决办法有两种:

  • 方案1(优先推荐,若允许修改源码):去掉Service类中success方法的final修饰符,修改后Mockito就能正常模拟该方法。
  • 方案2(无法修改源码时使用):启用Mockito的Final Mock功能:
    1. 给项目添加mockito-inline依赖(版本需与Mockito核心版本一致);
    2. 在src/test/resources/mockito-extensions目录下创建org.mockito.plugins.MockMaker文件,文件内容仅需一行:mock-maker-inline,即可全局启用final方法的mock能力。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 17:17:36