基于java反射的Spring事务代理下的JUnit测试

本文探讨了一种提高JUnit测试效率的方法,特别是在处理复杂后台程序时。通过利用Java反射,可以在Spring框架下直接访问并测试目标类,避免了不必要的依赖和繁琐的数据构造。文中介绍了作者在尝试获取测试类实例时遇到的问题,即因Spring的事务代理导致无法直接通过`context.getBean()`获取bean。在深入研究Spring实现并搜索解决方案后,找到了正确的方法,解决了问题,从而实现了更高效的单元测试。
摘要由CSDN通过智能技术生成

最近在对一个比较复杂的java后台程序进行单元测试,需要使用JUnit测试框架。但是由于后台业务太过复杂,甚至构造比较完整的测试数据都要花上一天的时间才能够搞定。一开始我采用最笨的方法,从最外部调用该API,需要一层一层的往下调用才能调到我需要测试的程序,这样的方法固然是可靠、可行的。但是,感觉这背离的unit testing的初衷,一些只是与被测程序有一些依赖关联的程序也要被测试,而且要构造非常复杂的数据,最后的结果很可能是降低了测试效率,最后还不一定能够达到测试目的。

那如何才能变得更加高效又能够达到测试的目的?这要感谢一个小伙伴的提醒,利用java反射就可以通过Junit测试代码来访问被测的类了。

该项目使用了Spring框架,于是我的第一版的测试代码是这样写的:

Test test = context.getBean("test");

Method getMethod = Test.class.getDeclaredMethod("getMethod", new Class[] {String.class});
getMethod.setAccessible(true);
Clazz obj = getMethod.invoke(test, "test");

可是这样写,最终居然发现我并不能取到Test类的实例。。我实在不知道我做错了什么。。结果java老鸟给我的意见仔细看看Spring的实现方式。结果我看了一下注册bean的java文件,是这样的:

<bean id="test" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
      <property name="transactionManager" ref="transactionManager" />
      <property name="target" ref="test" />
      <property name="transactionAttributes">
        <props>
          <prop key="get*">PROPAGATION_REQUIRED,-RuntimeException,-DaoException,-NexasException
          </prop>
        </props>
      </property>
</bean>

项目中使用了Spring的事务代理,之前的Test test = context.getBean(“test”);这种写法就有问题,取不到bean,经过一番google终于得到了问题的正解,于是有了Version 2:

Test test = (Test) getTargetObject(context.getBean("test"));

Method getMethod = Test.class.getDeclaredMethod("getMethod", new Class[] {String.class});
getMethod.setAccessible(true);
Clazz obj = getMethod.invoke(test, "test");

public static Object getTargetObject(Object proxy) throws Exception {
    if (!AopUtils.isAopProxy(proxy)) {
        return proxy;
    }
    return getTargetObject(getProxyTargetObject(proxy));
}

private static Object getProxyTargetObject(Object proxy) throws Exception {
    Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
    h.setAccessible(true);
    AopProxy aopProxy = (AopProxy) h.get(proxy);
    Field advised = aopProxy.getClass().getDeclaredField("advised");
    advised.setAccessible(true);
    return ((AdvisedSupport) advised.get(aopProxy)).getTargetSource().getTarget();
}

至此,一切搞定!学到就很多东西。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值