Java Mockito测试:如何检测非私有方法抛出的包私有异常?
问题描述
测试com.googlecode.jsonrpc4j库相关代码时,预期会抛出HttpException,编写了如下测试代码:
Exception exception = assertThrows(HttpException.class, () -> this.myApi.getInformation(date1, date2) );
同时导入了异常类:
import com.googlecode.jsonrpc4j.HttpException;
但收到错误提示:
'com.googlecode.jsonrpc4j.HttpException' is not public in 'com.googlecode.jsonrpc4j'.
Cannot be accessed from outside package
目前临时方案是断言抛出RuntimeException,但想找更优的测试方法。
更优测试方法
方法1:精准校验异常的类信息与属性
捕获RuntimeException后,通过校验异常的全类名、消息或内部属性(如HTTP状态码)来确认是目标HttpException,比单纯断言RuntimeException更精准:
RuntimeException exception = assertThrows(RuntimeException.class, () -> this.myApi.getInformation(date1, date2) ); // 校验异常的实际类型 assertEquals("com.googlecode.jsonrpc4j.HttpException", exception.getClass().getName()); // 如果异常包含状态码等属性,可通过反射绕过封装校验 Field statusCodeField = exception.getClass().getDeclaredField("statusCode"); statusCodeField.setAccessible(true); assertEquals(400, statusCodeField.getInt(exception)); // 示例:校验400状态码
方法2:通过反射加载非公开异常类
直接用全类名通过反射获取HttpException的Class对象,这样就能在assertThrows中直接指定目标异常类型,无需导入:
Class<?> httpExceptionClass = Class.forName("com.googlecode.jsonrpc4j.HttpException"); Exception exception = assertThrows((Class<? extends Exception>) httpExceptionClass, () -> this.myApi.getInformation(date1, date2) );
这种方式能保持测试用例的精准性,同时绕过非公开类的访问限制。
方法3:封装复用异常校验逻辑
如果多个测试用例都需要校验该异常,可以封装一个工具方法,统一处理校验逻辑:
public static void assertThrowsHttpException(Runnable testRunnable) { RuntimeException exception = assertThrows(RuntimeException.class, testRunnable); assertTrue(exception.getClass().getName().equals("com.googlecode.jsonrpc4j.HttpException")); // 可添加更多自定义校验,比如状态码、错误消息等 }
测试时直接调用工具方法即可:
assertThrowsHttpException(() -> this.myApi.getInformation(date1, date2));
内容的提问来源于stack exchange,提问作者Prasannjeet Singh
相关产品推荐
相关产品推荐

