首页
登录 | 注册

JVM之字节码——字节码增强应用(二)

2、Mock接口
      单元测试中的一个很重要的功能是mock外部接口。也就是说,对于指定的的接口,传入指定的借口,调用会返回指定的值。这个功能可以通过直接修改接口实现的方法来实现。
    2.1 Mock一个接口
     例如有这样的一个Servier接口:
  1. public interface Service {
  2.       List<Integer> service(List<Integer> param);

  3. }
  以及对应的实现类:
  1. public class ServiceImpl implements Service {
  2.        @Override
  3.        public List<Integer> service(List<Integer> param) {
  4.            List<Integer> result = null;
  5.            // ... xxx service
  6.            // .... xxx method
  7.            return result;
  8.       }
  9. }
 还有对应的单测类:

  1. public class ServiceTest {
  2.        @Mocked
  3.        private Service service = new ServiceImpl();
  4.       
  5.        @Test
  6.        public void test(){
  7.             List<Integer> result = service.service( null);
  8.              if(result == null){
  9.                   System. out.println( "return null");
  10.             } else{
  11.                   System. out.println( "return not null" );
  12.             }
  13.       }

  14.      }
      我们现在需要mock其中的service接口的实现类。假如我们现在要求在参数为null的条件下返回值为一个非空的数组。
 那么我们可以在测试用例跑之前,先用Javassit修改ServiceImpl的class文件使得test方法返回一个ArrayList。实现如下:

  1. public static void modifyMethod(CtClass clazz,CtMethod method) throws Exception{
  2.             
  3.             StringBuilder body = new StringBuilder();
  4.             body.append( "{if($1==null) return new java.util.ArrayList();else return null;}");
  5.             method.setBody(body.toString());
  6.             
  7.       }
这里的实现很简单,我们使用Javassist直接把test方法的方法体替换为:

  1. if(param == null)//在Javassist里用$1代表第一个参数。
  2.      return new java.util.ArrayList();
  3. else
  4.      return null;

这样就可以实现我们需要的mock掉的方法。
  
   2.2 查找需要Mock掉的方法
因为我们不能Mock掉所有的方法,所以需要根据具体的要求来Mock指定的方法,我们这里的要求是mock掉service方法,所以只需要查找到名称为service的方法来mock即可。
 下面的方法用来查找我们要修改的service方法:
  1. public static void mock(CtClass ctClass) throws Exception{
  2. //1、查找名称为service的方法
  3.         CtMethod method = ctClass.getDeclaredMethod( "service");
  4. //2、调用上面的方法来Mock调上面找到的service方法
  5.          modifyMethod(ctClass, method);
  6. }
  2.3 调用TestCase
  接下来是如何调用我们的TestCase使得我们的Mock生效,因为我们是修改了ServiceImpl的class文件,所以在调用TestCase之前,需要先完成class文件的修改。具体的代码如下:
  1. public static void main(String[] args) throws Exception{
  2.                          //1、取得ServiceImpl
  3.             ClassPool cp = ClassPool. getDefault();
  4.             CtClass cc = cp.get( "ServiceImpl");
  5.                          //2、Mock掉service方法
  6.              mock(cc);
  7.                          //3、写入到class文件里
  8.             cc.writeFile( "F:/workspace/JavaAssit/bin/" );
  9.                          //4、调用TestCase
  10.             ServiceTest serviceTest = new ServiceTest();
  11.             serviceTest.test();
  12.             
  13.       }
运行一下,输出结果为return not null,这表明我们的mock代码起作用了。


相关文章

  • SNMP从入门到开发:基础篇
    SNMP协议入门 1.引言 基于TCP/IP的网络管理包含3个组成部分: 1) 一个管理信息库MIB(Management Information Base).管理信息库包含所有代理进程的所有可被查询和修改的参数.RFC 1213[McCl ...
  • 官方翻译不当导致的PowerShell运行失败一例
    今天我在PowerShell.com看到一篇文章,是关于Gridview的应用,觉得挺好,决定自己尝试一下.但是实际操作的时候却失败了,然后开始了漫长的排错. http://powershell.com/cs/blogs/tips/arch ...
  • 主要参数 -c 统计字节数. -l 统计行数. -m 统计字符数.这个标志不能与 -c 标志一起使用. -w 统计字数.注意,这里的字指的是由空格,换行符等分隔的字符串. 统计文件行数,词数和字节数 打印结果表明该文件有1行,1个词,7字节 ...
  • DevExpress 在今年6月份发布了正式的2015版本,2015在旧版基础上有明显的升级改进,尤其是DevExtreme.Winforms.VCL几个控件更新比较 多.本人历经2个月,翻译了官网关于2015版升级的介绍,特将翻译的文档地 ...
  • 本文旨在用最通俗的语言讲述最枯燥的基本知识 今日,看到有些文章对码农和程序员做了一些界限划定和差异分析,吓得作者赶紧研究一下自己属于哪个身份,但当仔细查看了这些文章后,发现其实对于写代码的人来说,无非就像周星驰嘴里的"龙套&quo ...
  • linux下C语言实现动态分配的缓冲区保存多个ascii码字符串首地址
    操作系统:ubuntu10.04 前言     很多时候,pc控制下位机,都是通过串口或web,多以ascii码直接通信.在数据较少时,可直接申请一个缓冲区,发送所需数据:但是在很多时候,发送的数据会非常大,直接申请一个非常大的缓冲区并不是 ...

2019 unjeep.com webmaster#unjeep.com
12 q. 0.014 s.
京ICP备10005923号