Java中ClientFactory类catch块单元测试编写实现方法
问题描述
现有一个继承自ClientInfo的ClientFactory类,需要为该类编写单元测试。目前try代码块的测试覆盖很容易实现,但无法编写出能够覆盖catch代码块的测试用例,待测试代码如下:
public class ClientFactory extends ClientInfo { private static final String PROVIDER_PATH = "com.devo.com.providers"; public ClientFactory(List<String> providers) { super(getProviderListOfObjects(providers)); } private static List<Provider> getProviderListOfObjects(List<String> providers) { List<Provider> providersObject = new ArrayList<>(); for (String provider : providers) { provider = PROVIDER_PATH + "." + provider; try { Class<?> c = Class.forName(provider); Provider providerObj = (Provider) c.newInstance(); providersObject.add(providerObj); } catch (ClassNotFoundException e) { String message = String.format("Provider %s not found in package %s.", provider, PROVIDER_PATH); log.error(message); } catch (InstantiationException | IllegalAccessException e) { String message = String.format("Unable to create new instance of %s class.", provider); log.error(message); } } return ImmutableList.copyOf(providersObject); } }
测试实现方案
要覆盖三个异常对应的两个catch分支,只需要针对性构造触发对应异常的入参即可,不需要特殊黑科技:
- 覆盖ClassNotFoundException分支
直接传入一个不存在的provider名称即可,比如入参传Arrays.asList("NotExistProvider"),代码拼接后的全限定类名是com.devo.com.providers.NotExistProvider,类加载阶段就会抛出ClassNotFoundException,自动进入对应catch块。测试时可以绑定测试日志追加器,校验对应错误日志是否输出,确认分支被执行。 - 覆盖InstantiationException分支
这个异常的触发条件是目标类可以被加载,但无法被实例化,比如类是抽象类、接口、没有公开无参构造。你只需要在测试源码的com.devo.com.providers路径下新建一个实现Provider接口的抽象类,把这个抽象类的类名作为入参传入,Class.forName能正常加载类,但调用newInstance()时会抛出实例化异常,进入catch块。 - 覆盖IllegalAccessException分支
这个异常的触发条件是目标类存在,但构造函数权限不足无法访问。同样在测试源码的对应包路径下新建一个Provider实现类,把它的无参构造函数设置为private或者protected,反射调用构造方法时就会抛出权限访问异常,进入对应catch块。
补充说明:如果不想在测试目录下建真实测试类,也可以用PowerMock这类支持静态方法Mock的测试工具,直接Mock
Class.forName和Class.newInstance方法,指定方法抛出对应异常就能触发分支。不过更推荐用真实测试类的方案,不需要依赖字节码修改工具,测试逻辑更稳定,也不会因为JDK版本升级出现兼容问题。
内容的提问来源于stack exchange,提问作者Abhishek Ranjan
相关产品推荐
相关产品推荐

