(私有方法?我偏要访问!)测试需要访问Service层私有方法时,你应该这样办!
前言
最近在写测试,TDD(测试驱动开发),然后写到了一个测试方法时,我还是照常调用了Service层,自己写的“public” 的 私有方法,
(为什么这样说,因为这个方法只是为了提供了这个类的方法中某一个的方法使用,而创建的。没有任何复用可言,但是因为为了测试,所以写成了public,以便调用。)
我一直很诧异,为什么一直要这样搞,缺少了代码的完整真实可读性,可能会让读代码的人第一反应造成不必要的误解,然后我就开始了接下来的探究。
目标
把代码改成 private 关键字修饰,不加任何静态修饰符或者单例修饰等等。保证代码完整真实性。
代码
AccountServicelmpl内代码
不用在意方法内的内容
private String subCardBinLastChar(String cardNo) { if (cardNo.length() <= CARD_BIN_PREFIX_MIN_LENGTH) { throw new ServiceException(ResultCode.BANK_NON_SUPPORT); } if (cardNo.length() > CARD_BIN_PREFIX_MAX_LENGTH) { return StringUtils.substring(cardNo, 0, CARD_BIN_PREFIX_MAX_LENGTH); } return StringUtils.substring(cardNo, 0, cardNo.length() - 1); } |
写了工具类用于调用这个一个参数的方法
/** * 用于测试返回Service静态方法 * @author FYF * @date Created in 9:40 2020/6/22 */ public class ExecutePrivateMethods { public static <T> Object ClassReflect(Class<T> TClass, String method) { Class cl = null; try { cl = TClass; Object Clazz = cl.newInstance(); Method m1 = cl.getDeclaredMethod(method); m1.setAccessible(true); Object invoke = m1.invoke(Clazz); return invoke; } catch (Exception e) { throw new ServiceException(e.getMessage()); } } //带一个参数 public static <T> Object ClassReflect(Class<T> TClass, String method,Object obj) { Class cl = null; try { cl = TClass; Object Clazz = cl.newInstance(); Method m1 = cl.getDeclaredMethod(method,obj.getClass()); m1.setAccessible(true); Object invoke = m1.invoke(Clazz,obj); return invoke; } catch (Exception e) { throw new ServiceException(e.getMessage()); } } } |
测试
@ParameterizedTest @ValueSource(strings = {"12345678901234"}) void testSubCardBinLengthForLong(String cardNo) { Object subCardBinLastChar = ExecutePrivateMethods.ClassReflect(AccountServiceImpl.class, "subCardBinLastChar", cardNo); String cardBin = subCardBinLastChar.toString(); log.info("cardBin:{}", cardBin); assertEquals(AccountServiceImpl.CARD_BIN_PREFIX_MAX_LENGTH, cardBin.length()); } |
测试结果:成功
关键代码
Class cl = null; try { cl = TClass.class(替换成你要调用的class); Object Clazz = cl.newInstance(); Method m1 = cl.getDeclaredMethod("methonName"(方法名),String(参数类型).getClass); m1.setAccessible(true); Object invoke = m1.invoke(Clazz,"参数"(参数)); return invoke; } catch (Exception e) { throw new ServiceException(e.getMessage()); } } } |
总结
用反射的机制去映射出一个类,然后去调用它的私有方法,因为反射可以把私有方法也映射出来。
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。