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

如何在Mockito中模拟构造方法抛出异常(不使用PowerMock)

Mockito模拟构造方法抛出异常(无需PowerMock)

你原来尝试用when(??).thenThrow(ex)的思路不可行,因为when是用来配置mock实例的方法行为,而构造方法的执行发生在mock实例创建之前,Mockito的MockedConstruction机制是拦截构造调用并生成mock实例,无法通过when语法直接让构造本身抛出异常。

针对你遇到的临时方案中异常被包装为二级原因的问题,这里提供两种解决思路:

方案一:调整断言逻辑,验证包装异常的原因

Mockito会将MockInitializer中抛出的异常包装为MockitoException,你可以捕获这个包装异常,然后验证其内部的原因是否为你预期的异常:

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.mockito.MockedConstruction;
import org.mockito.exceptions.base.MockitoException;
import static org.junit.jupiter.api.Assertions.*;

@Test
void exceptionAtConstruction() {
    final RuntimeException expectedException = new RuntimeException("构造失败");
    
    try (MockedConstruction<SomeClass> ignored = Mockito.mockConstruction(SomeClass.class,
            (mock, context) -> {
                throw expectedException;
            })) {
        // 捕获Mockito包装后的异常
        MockitoException wrappedException = assertThrows(MockitoException.class, SomeClass::new);
        // 验证异常根源是我们预期的RuntimeException
        assertSame(expectedException, wrappedException.getCause());
    }
}

方案二:基于测试场景选择替代实现

需要明确的是,MockedConstruction的核心目的是生成mock实例,而非模拟构造方法失败。如果你的测试需求只是验证代码在构造方法抛出异常时的行为,而非需要mockSomeClass的实例,那么可以考虑不依赖Mockito,比如手动创建SomeClass的测试子类来模拟场景:

class TestSomeClass extends SomeClass {
    public TestSomeClass() {
        throw new RuntimeException("构造失败");
    }
}

@Test
void exceptionAtConstruction() {
    assertThrows(RuntimeException.class, TestSomeClass::new);
}

如果必须使用Mockito完成这个场景,方案一的断言调整是最直接的可行方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 18:33:30