51Testing软件测试论坛

标题: TDD测试时,需要访问Service层私有方法时,你应该这样办! [打印本页]

作者: lsekfe    时间: 2020-7-24 10:38
标题: TDD测试时,需要访问Service层私有方法时,你应该这样办!
 (私有方法?我偏要访问!)测试需要访问Service层私有方法时,你应该这样办!
  前言
  最近在写测试,TDD(测试驱动开发),然后写到了一个测试方法时,我还是照常调用了Service层,自己写的“public” 的 私有方法,
  (为什么这样说,因为这个方法只是为了提供了这个类的方法中某一个的方法使用,而创建的。没有任何复用可言,但是因为为了测试,所以写成了public,以便调用。)
  我一直很诧异,为什么一直要这样搞,缺少了代码的完整真实可读性,可能会让读代码的人第一反应造成不必要的误解,然后我就开始了接下来的探究。
  目标
  把代码改成 private 关键字修饰,不加任何静态修饰符或者单例修饰等等。保证代码完整真实性。
  代码
  AccountServicelmpl内代码
  不用在意方法内的内容
  1. private String subCardBinLastChar(String cardNo) {

  2.   if (cardNo.length() <= CARD_BIN_PREFIX_MIN_LENGTH) {

  3.   throw new ServiceException(ResultCode.BANK_NON_SUPPORT);

  4.   }

  5.   if (cardNo.length() > CARD_BIN_PREFIX_MAX_LENGTH) {

  6.   return StringUtils.substring(cardNo, 0, CARD_BIN_PREFIX_MAX_LENGTH);

  7.   }

  8.   return StringUtils.substring(cardNo, 0, cardNo.length() - 1);

  9.   }
复制代码

写了工具类用于调用这个一个参数的方法

  1. /**

  2.   * 用于测试返回Service静态方法

  3.   * [url=home.php?mod=space&uid=267564]@Author[/url] FYF

  4.   * [url=home.php?mod=space&uid=315144]@date[/url] Created in 9:40 2020/6/22

  5.   */

  6.   public class ExecutePrivateMethods {

  7.   public static <T> Object ClassReflect(Class<T> TClass, String method) {

  8.   Class cl = null;

  9.   try {

  10.   cl = TClass;

  11.   Object Clazz = cl.newInstance();

  12.   Method m1 = cl.getDeclaredMethod(method);

  13.   m1.setAccessible(true);

  14.   Object invoke = m1.invoke(Clazz);

  15.   return invoke;

  16.   } catch (Exception e) {

  17.   throw new ServiceException(e.getMessage());

  18.   }

  19.   }

  20.   //带一个参数

  21.   public static <T> Object ClassReflect(Class<T> TClass, String method,Object obj) {

  22.   Class cl = null;

  23.   try {

  24.   cl = TClass;

  25.   Object Clazz = cl.newInstance();

  26.   Method m1 = cl.getDeclaredMethod(method,obj.getClass());

  27.   m1.setAccessible(true);

  28.   Object invoke = m1.invoke(Clazz,obj);

  29.   return invoke;

  30.   } catch (Exception e) {

  31.   throw new ServiceException(e.getMessage());

  32.   }

  33.   }

  34.   }


  35.   测试



  36.    @ParameterizedTest

  37.   @ValueSource(strings = {"12345678901234"})

  38.   void testSubCardBinLengthForLong(String cardNo) {

  39.   Object subCardBinLastChar = ExecutePrivateMethods.ClassReflect(AccountServiceImpl.class, "subCardBinLastChar", cardNo);

  40.   String cardBin = subCardBinLastChar.toString();

  41.   log.info("cardBin:{}", cardBin);

  42.   assertEquals(AccountServiceImpl.CARD_BIN_PREFIX_MAX_LENGTH, cardBin.length());

  43.   }
复制代码


测试结果:成功
[attach]129095[/attach]
关键代码
  1. Class cl = null;

  2.   try {

  3.   cl = TClass.class(替换成你要调用的class);

  4.   Object Clazz = cl.newInstance();

  5.   Method m1 = cl.getDeclaredMethod("methonName"(方法名),String(参数类型).getClass);

  6.   m1.setAccessible(true);

  7.   Object invoke = m1.invoke(Clazz,"参数"(参数));

  8.   return invoke;

  9.   } catch (Exception e) {

  10.   throw new ServiceException(e.getMessage());

  11.   }

  12.   }

  13.   }
复制代码
总结
  用反射的机制去映射出一个类,然后去调用它的私有方法,因为反射可以把私有方法也映射出来。


作者: jiazurongyu    时间: 2020-7-24 14:28
Jdk反射。




欢迎光临 51Testing软件测试论坛 (http://bbs.51testing.com/) Powered by Discuz! X3.2