浅谈Jmockit使用

转自http://blog.csdn.net/changsu4615/article/details/46802517。如有疑问请联系我删除。

最近公司里要求使用Jmockit来辅助单元测试。之前也没接触过,研究了几天,今天就跟大家谈谈我怎么使用Jmockit。写一个小例子供大家参考。

  如有不对的地方还请大家多多指正

  对于Mock的作用这里就不详细介绍了,不清楚的可以自行百度。笔者使用的是1.15版本的Jmockit(默认读者已经把相应的包导好)

  在开始测试之前我们先写一个简单的Java类,代码如下

 

[java]  view plain  copy
  1. public class GetServiceForBook {  
  2.   
  3.   
  4.   public int getService(String bookType) {  
  5.   
  6.     if ("novel".equals(bookType)){  
  7.       return 1;  
  8.     }  
  9.     else {  
  10.       return 2;  
  11.     }  
  12.   }  
  13. }  

  以上是一个极其简单的一个Java类,里面定义了一个getService方法。看了这个方法后可以确定,调用这个方法后得到的结果不是1就2.下面我们就来写一个小单元测试。

[java]  view plain  copy
  1. import static org.junit.Assert.*;  
  2. import org.junit.Test;  
  3.   
  4. public class GetServiceForBookTest {  
  5.     
  6.   private GetServiceForBook getServiceForBook = new GetServiceForBook();  
  7.     
  8.   @Test  
  9.   public void testBookService() {  
  10.         
  11.    int test = getServiceForBook.getService("novel");  
  12.       
  13.    assertEquals(1,test);  
  14.  }  
  15. }  

  对于上面的单元测试我相信不会有人看不懂,而且简单运行一下就是一个长长的绿条。那下面我们就开始使用Mock来“修改”我们的GetServiceForBook类。

  刚刚也说明了,对于getService方法的返回值不是1就是2。那如果我想让getService返回3怎么办?很简单,使用Mock。先上Expectations的方式。

[java]  view plain  copy
  1. import static org.junit.Assert.*;  
  2. import mockit.Expectations;  
  3. import mockit.Injectable;  
  4.   
  5. import org.junit.Test;  
  6.   
  7. public class GetServiceForBookTest {  
  8.     
  9.   @Injectable  
  10.   private GetServiceForBook getServiceForBook;  
  11.     
  12.   @Test  
  13.   public void testBookService() {  
  14.         
  15.    new Expectations(){  
  16.      {  
  17.        getServiceForBook.getService(anyString);  
  18.        result = 3;  
  19.        times = 1;  
  20.      }  
  21.        
  22.    };  
  23.       
  24.    int test = getServiceForBook.getService("novel");  
  25.    assertEquals(3,test);  
  26.  }  
  27. }  
  以上就是使用Mock的方式把getService方法给“修改”了。所以底下的断言是看test和3的比较。很明显,这里用了Expectations把getService的返回值改成了3,也就是说在这个测试里不论我传进去的参数是什么,它的返回都是3.(使用@Injectable系统会自动注入,创建实例。)下面在给一个使用MockUp方式

[java]  view plain  copy
  1. import static org.junit.Assert.*;  
  2. import mockit.Mock;  
  3. import mockit.MockUp;  
  4.   
  5. import org.junit.Test;  
  6.   
  7. public class GetServiceForBookTest {  
  8.     
  9.   
  10.   private GetServiceForBook getServiceForBook = new GetServiceForBook();  
  11.     
  12.   @Test  
  13.   public void testBookService() {  
  14.       
  15.    new MockUp(){  
  16.      @Mock  
  17.      public int getService(String bookType)  
  18.      {  
  19.        return 3;  
  20.      }  
  21.    };  
  22.       
  23.    int test = getServiceForBook.getService("novel");  
  24.    assertEquals(3,test);  
  25.  }  
  26. }  
  可以看出这两个Mock的结果是一样的都是把getService的方法改成3. 但是MockUp方式跟Expectations不同的是,MockUp把getService方法重新写了一遍并不像Expectations那样只要设定下变量就可以改变getService方法。


  现在,我们稍微修改下原来的GetServiceForBook类。

[java]  view plain  copy
  1. package cn.com.liandisys.book.service;  
  2.   
  3. public class GetServiceForBook {  
  4.   
  5.   
  6.   JustForTest jft = new JustForTest();  
  7.   
  8.   public GetServiceForBook()  
  9.   {  
  10.   
  11.   }  
  12.   
  13.   public GetServiceForBook(JustForTest jft)  
  14.   {  
  15.     this.jft = jft;  
  16.   }  
  17.   
  18.   public int getService(String bookType) {  
  19.   
  20.     boolean flag = jft.getResult();  
  21.     System.out.println(flag);  
  22.     if ("novel".equals(bookType)) {  
  23.       return 1;  
  24.     }  
  25.     else {  
  26.       return 2;  
  27.     }  
  28.   }  
  29. }  

  看到里面多了一个JustForTest的类,下面把JustForTest类代码贴出来

[java]  view plain  copy
  1. public class JustForTest {  
  2.   
  3.   public boolean getResult() {  
  4.     return false;  
  5.   }  
  6.   
  7. }  
依然是一个简单的Java类,我们可以看出这个JustForTest类里有一个getResult的方法,这个方法返回的永远是false. 在GetServiceForBook类里申明了一个JustForTest类并调用了getResult方法然后打印出来。不出意外这个输出结果应该永远都是false。那下面我们用Mock把getResult方法“修改”成true。

[java]  view plain  copy
  1. import static org.junit.Assert.*;  
  2. import mockit.Expectations;  
  3. import mockit.Injectable;  
  4. import mockit.Tested;  
  5.   
  6. import org.junit.Test;  
  7.   
  8. public class GetServiceForBookTest {  
  9.     
  10.   @Tested  
  11.   private GetServiceForBook getServiceForBook;  
  12.     
  13.   @Injectable  
  14.   private JustForTest jft;  
  15.     
  16.   @Test  
  17.   public void testBookService() {  
  18.       
  19.    new Expectations(){  
  20.        
  21.      {  
  22.         jft.getResult();  
  23.         result = true;  
  24.         times = 1;  
  25.      }  
  26.        
  27.    };  
  28.       
  29.    int test = getServiceForBook.getService("novel");  
  30.    assertEquals(1,test);  
  31.  }  
  32. }  

  由于我们并没有mock掉getService所以返回值不是1就是2,对于上面的单元测试,给的参数是novel那返回值就应该是1。 然后我们运行一下可以发现控制台输出的是true而不是false了,这是因为我们把JustForTest类的getResult方法给Mock掉了。

  里面还有两个注解一个@Tested一个是@Injectable。第一个@Tested不能变只能是这个,第二个可以写成@Mocked。如果第一个改成@Mocked的话输出结果就变成0,也就是说不过你的参数是什么结果都是输出0。这是因为在你使用Mocked注解时,如果没有进行“修改”,那系统就会自己帮你把这个类里的所有方法都Mock掉,而mock的内容就是返回默认值。(int的默认值是0)。

 下面给出使用MockUp方式的

[java]  view plain  copy
  1. import static org.junit.Assert.*;  
  2. import mockit.Mock;  
  3. import mockit.MockUp;  
  4.   
  5. import org.junit.Test;  
  6.   
  7. public class GetServiceForBookTest {  
  8.     
  9.   private GetServiceForBook getServiceForBook = new GetServiceForBook();  
  10.     
  11.   @Test  
  12.   public void testBookService() {  
  13.       
  14.     new MockUp(){  
  15.       @Mock  
  16.       public boolean getResult()  
  17.       {  
  18.         return true;  
  19.       }  
  20.     };  
  21.       
  22.     int test = getServiceForBook.getService("novel");  
  23.     assertEquals(1,test);  
  24.  }  
  25. }  
  这里就不多解释了,跟上面的MockUp例子很像,同样也是把getResult输出true。

  通过查阅Jmockit文档,发现MockUp有一个方法叫getMockInstance。也就是创建一个Mock实例。我们可以这样理解,每一个需要被Mock的代码都可以看作是一个对象。就拿上面getResult例子来说JustForTest可以把它看作是一个Mock对象。所以我们还可以改成下面的形式。

[java]  view plain  copy
  1. import static org.junit.Assert.*;  
  2. import mockit.Mock;  
  3. import mockit.MockUp;  
  4.   
  5. import org.junit.Test;  
  6.   
  7. public class GetServiceForBookTest {  
  8.     
  9.   private GetServiceForBook getServiceForBook;  
  10.     
  11.   @Test  
  12.   public void testBookService() {  
  13.       
  14.     JustForTest mock = new MockUp(){  
  15.       @Mock  
  16.       public boolean getResult()  
  17.       {  
  18.         return true;  
  19.       }  
  20.     }.getMockInstance();  
  21.       
  22.     getServiceForBook = new GetServiceForBook(mock);  
  23.     int test = getServiceForBook.getService("novel");  
  24.     assertEquals(1,test);  
  25.  }  
  26. }  
  这就是为什么我去重写getServiceForBook的构造函数,把Mock创建出来的对象赋给getServiceForBook里的JustForTest,这样也能达到Mock的目的


  这次就先写到这里,其实对于Jmockit来说,这个只是沧海一栗,里面还有多东西需要研究,这里就先跟大家分享这么多,希望能对读者有用。

 这是我第一次写博客,可能还有很多不足的地方,还请大大多多指教。

你可能感兴趣的:(浅谈Jmockit使用)