单元测试工具类ReflectionTestUtils

发表于:2021-11-29 09:35

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:我有一只喵喵    来源:稀土掘金

  前言
  在写单元测试时,是否经常遇到要测试的目标类中有很多私有注入的变量呢?然而我们经常并没有报漏此私有属性的getter and setter,因为这些私有属性的注入可能是通过配置文件,或者其他渠道,是在程序启动时根据环境不同或者其他因素来决定的,所以当我们测试的时候,就需要通过为该属性设置不同的值而来测试各种分支case,但是前面已经说了一般这种变量都是私有变量,如果说专门为了测试而将修饰符改为public/protected 那未免过于暴力....
  于是乎,大家常见的做法可能就是写一堆反射去修改,如果只有一处地方还好,但是如果需要测试此种场景的过多,那是不是写都写烦了,所以ReflectionTestUtils解放你的双手。
  用法
  首先搞一个service来辅助:
  public class TestServiceImpl {
      private String configId = "11111";
      public String getConfigId() {
          return configId;
      }
  }

  新建一个测试类:
  class TestServiceImplTest {
      private TestServiceImpl testService = new TestServiceImpl();
      @Test
      void getConfigId() {
          System.out.println("修改前:" + testService.getConfigId());
          ReflectionTestUtils.setField(testService,"configId","2222");
          System.out.println("修改后:" + testService.getConfigId());
      }
  }
  输出:
  修改前:11111
  22:35:40.628 [main] DEBUG org.springframework.test.util.ReflectionTestUtils - Setting field 'configId' of type [null] on target object [com.cf.springboot.TestServiceImpl@45018215] or target class [class com.cf.springboot.TestServiceImpl] to value [2222]
  修改后:2222

  通过输出以及代码,可以看到非常的简单,一行代码即可完成私有属性的更改,是不是十分的方便!
  原理
  这里就简单贴一下代码,看看:
  public static void setField(@Nullable Object targetObject, @Nullable Class<?> targetClass, @Nullable String name, @Nullable Object value, @Nullable Class<?> type) {
      Assert.isTrue(targetObject != null || targetClass != null, "Either targetObject or targetClass for the field must be specified");
      if (targetObject != null && springAopPresent) {
          targetObject = AopTestUtils.getUltimateTargetObject(targetObject);
      }
      if (targetClass == null) {
          targetClass = targetObject.getClass();
      }
      Field field = ReflectionUtils.findField(targetClass, name, type);
      if (field == null) {
          throw new IllegalArgumentException(String.format("Could not find field '%s' of type [%s] on %s or target class [%s]", name, type, safeToString(targetObject), targetClass));
      } else {
          if (logger.isDebugEnabled()) {
              logger.debug(String.format("Setting field '%s' of type [%s] on %s or target class [%s] to value [%s]", name, type, safeToString(targetObject), targetClass, value));
          }
          ReflectionUtils.makeAccessible(field);
          ReflectionUtils.setField(field, targetObject, value);
      }
  }

  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号