1. 程式人生 > >使用mock進行單元測試

使用mock進行單元測試

在service層,使用mock來測試程式碼。而不再使用Juint測試

JUint是java單元測試的框架,已經在Eclipse中預設的安裝。目前主流的有JUnit3和JUnit4.JUint3中,測試用例需要繼承TestCase類,JUint4中,測試用例無需繼承TestCase類,只需要使用@Test等註解。

JUint4主要通過註解的方式來識別測試方法。目前支援的主要註解有:

@BeforeClass全域性只會執行一次,而且是第一個執行。

@Before在測試方法執行之前執行

@Test測試方法

@After在測試方法執行之後允許

@AfterClass全域性只會執行一次,而且是最後一個執行

@Ignore忽略此方法

Juint3和JUint4都提供了一個Assert類。Assert類中定義了很多靜態方法來進行斷言。

Mockito與JUint不同,並不是單元測試框架。它是用於生成模擬物件或者直接點說,就是“假物件”的工具。

Mock/Stub

Mock和Stub是兩種測試程式碼功能的方法。Mock側重於對功能的模擬,Stub測重於對功能的測試重現,例如對List介面。Mock會直接對List進行模擬,而Stub會新建一個實現了List的TestList,在其中編寫測試的程式碼。

強烈建議優先選擇Mock方式,因為Mock方式下,模擬程式碼與測試程式碼放在一起,易讀性好,而且擴充套件性、靈活性都比Stub好。

比較流行的Mock

JMock

EasyMock

Mockito

powermock

其中EasyMcock和Mocking對於Java介面使用介面代理的方式來模擬。對於Java類使用繼承的方式來模擬(即會建立一個新的Class類)。Mockito支援spy方式。可以對例項進行模擬。但他們都不能對靜態方法和final類進行模擬。

Mockito是一個開源專案。Api相對於EasyMock更友好,與EasyMock不同的是,Mockito沒有錄製過程,只需要在“執行測試程式碼”之前對介面進行Stub,即設定方法的返回值或丟擲的異常。然後直接執行測試程式碼。執行期間呼叫Mock的方法,會返回預先設定的返回值或丟擲異常。最後再對測試程式碼進行驗證。

  1. mport static org.mockito.Mockito.*;  
  2. //建立Mock  
  3. List mockedList = mock(List.class);  
  4. //使用Mock物件  
  5. mockedList.add("one");  
  6. mockedList.clear();  
  7. //驗證行為  
  8. verify(mockedList).add("one");  
  9. verify(mockedList).clear();  

首先是配置 Mock 物件,、

List mock = mock( List.class );
when( mock.get(0) ).thenReturn( 1 );
assertEquals( "預期返回1", 1, mock.get( 0 ) );

Mockito支援 迭代風格 的返回值設定,

  • 第一種方式 when(i.next()).thenReturn("Hello").thenReturn("World");
  • 第二種方式 when(i.next()).thenReturn("Hello", "World");

上面的例子等價於:

when(i.next()).thenReturn("Hello");
when(i.next()).thenReturn("World");

第一次呼叫i.next()將返回”Hello”,第二次的呼叫會返回”World”。

對 void 方法不返回值,所以不能 when(mock.someMethod()).thenReturn(value) 這樣的語法,可以這樣

doNothing().when(i).remove();
doThrow(Throwable) 模擬返回異常
doThrow(new RuntimeException()).when(i).remove();

迭代風格 doNothing().doThrow(new RuntimeException()).when(i).remove();,這樣,第一次呼叫remove方法什麼都不做,第二次呼叫丟擲RuntimeException異常。

(1)如何將mock的類自動注入到待測類中?

在測試程式碼中,使用@Inject將service層注入,@Mock註釋Mapper。

public class AService {

}

public  class AServiceTest   extends Test4J{

@Inject(targets= { “ AService” })

@Mock

private AMapper aMapper;

}