51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

查看: 3199|回复: 1
打印 上一主题 下一主题

TDD测试时,需要访问Service层私有方法时,你应该这样办!

[复制链接]
  • TA的每日心情
    无聊
    13 小时前
  • 签到天数: 933 天

    连续签到: 5 天

    [LV.10]测试总司令

    跳转到指定楼层
    1#
    发表于 2020-7-24 10:38:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
     (私有方法?我偏要访问!)测试需要访问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.   }
    复制代码


    测试结果:成功

    关键代码
    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.   }
    复制代码
    总结
      用反射的机制去映射出一个类,然后去调用它的私有方法,因为反射可以把私有方法也映射出来。

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

    x
    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-4-19 22:48 , Processed in 0.065617 second(s), 23 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表