如何在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
相关产品推荐
相关产品推荐

