JUnit测试预期MalformedURLException却获UndeclaredThrowableException问题
问题解决:UndeclaredThrowableException替代预期的MalformedURLException
问题原因
UndeclaredThrowableException 通常是**动态代理(如Spring AOP代理)**导致的:当代理对象调用的方法抛出了未在代理接口中声明的检查型异常时,代理机制会将原始异常包装成UndeclaredThrowableException抛出。即使你的getDNSBasedUrl()方法已声明抛出MalformedURLException,如果测试中使用的是代理后的ServerConnection实例,就会出现这个包装异常。
解决办法
方法1:使用原始类实例而非代理对象
如果测试不需要代理逻辑,直接创建ServerConnection的原始实例,避免代理包装异常:
@Test(expected = MalformedURLException.class) public void gctNameSpace_Exception(){ // 直接new原始实例,而非通过依赖注入获取代理对象 ServerConnection connection = new ServerConnection(); connection.setNameSpace(null); String s = connection.getDNSBasedUrl(); }
方法2:修改测试用例,捕获并验证包装后的异常
如果必须使用代理对象,调整测试逻辑,捕获UndeclaredThrowableException并验证其内部的原始异常:
@Test public void gctNameSpace_Exception(){ ServerConnection connection = new ServerConnection(); // 或获取代理实例 connection.setNameSpace(null); try { connection.getDNSBasedUrl(); fail("Expected MalformedURLException to be thrown"); } catch (UndeclaredThrowableException e) { // 验证原始异常类型和消息 assert e.getCause() instanceof MalformedURLException; assertEquals("undefined namespace", e.getCause().getMessage()); } }
如果使用JUnit 5,可更简洁地用assertThrows:
import static org.junit.jupiter.api.Assertions.*; @Test public void gctNameSpace_Exception(){ ServerConnection connection = new ServerConnection(); connection.setNameSpace(null); UndeclaredThrowableException wrappedException = assertThrows(UndeclaredThrowableException.class, () -> connection.getDNSBasedUrl()); MalformedURLException originalException = (MalformedURLException) wrappedException.getCause(); assertEquals("undefined namespace", originalException.getMessage()); }
两种方法都不需要修改getUrl()或getDNSBasedUrl()的异常声明,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Sumit Kumar
相关产品推荐
相关产品推荐

