Chinaunix首页 | 论坛 | 博客
  • 博客访问: 619065
  • 博文数量: 69
  • 博客积分: 1891
  • 博客等级: 上尉
  • 技术积分: 1359
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-20 23:38
文章分类

全部博文(69)

文章存档

2012年(46)

2011年(23)

分类: Java

2012-09-05 13:58:08

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代码起作用了。

阅读(5463) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~