單元測試的思路是在不涉及依賴的狀況下測試代碼,通常是測試service層的方法,但實際的代碼常會涉及到依賴,一個可行的方法就是使用模擬對象來替換依賴對象。框架
Mockito 是一個流行 mock 框架,能夠和JUnit結合起來使用。Mockito 容許你建立和配置 mock 對象。使用Mockito能夠明顯的簡化對外部依賴的測試類的開發。maven
通常使用 Mockito 須要執行下面三步函數
模擬並替換測試代碼中外部依賴。單元測試
執行測試代碼測試
驗證測試代碼是否被正確的執行this
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <scope>test</scope> </dependency>
若是在代碼中靜態引用了org.mockito.Mockito.*;
,那你你就能夠直接調用靜態方法和靜態變量而不用建立對象,譬如直接調用 mock() 方法。spa
Mockito 還支持經過 @Mock
註解的方式來建立 mock 對象.net
使用註解,那麼必需要實例化 mock 對象。Mockito 在遇到使用註解的字段的時候,會調用 MockitoAnnotations.initMocks(this)
來初始化該 mock 對象。另外也能夠經過使用@RunWith(MockitoJUnitRunner.class)
來達到相同的效果。code
註解對象
調用方法:
when(….).thenReturn(….)能夠被用來定義當條件知足時函數的返回值,若是你須要定義多個返回值,能夠屢次定義。當你屢次調用函數的時候,Mockito 會根據你定義的前後順序來返回返回值。Mocks 還能夠根據傳入參數的不一樣來定義不一樣的返回值。譬如說你的函數能夠將anyString 或者 anyInt做爲輸入參數,而後定義其特定的放回值。
自定義方法的返回值
Mockito.when(方法).thenReturn(返回值)
Mockito.when(方法).thenReturn(返回值1).thenReturn(返回值2)
無返回值
對於無返回值的函數,咱們可使用doReturn(…).when(…).methodCall來得到相似的效果。例如咱們想在調用某些無返回值函數的時候拋出異常,那麼可使用doThrow 方法。
以下所示:
Mockito.doThrow(new IOException()).when(mockStream).close()
僅調用方法,但啥也不作
Mockito.doNothing().when(tagRepository).deleteByTagId(1)
注:tagRepository有一個方法是 deleteByTagId(int tagId)
驗證 query 方法是否被 MyDatabase 的 mock 對象調用
verify(databaseMock).query("* from t");
查看在傳入參數爲12的時候方法是否被調用
verify(test).testing(Matchers.eq(12));
方法是否被調用兩次
verify(test, times(2)).getUniqueId();
verify(mock, never()).someMethod("never called");
verify(mock, atLeastOnce()).someMethod("called at least once");
verify(mock, atLeast(2)).someMethod("called at least twice");
verify(mock, times(5)).someMethod("called five times");
verify(mock, atMost(3)).someMethod("called at most 3 times");
下面三種數據類型則不可以被測試
final classes
anonymous classes
primitive types
Mockito 不可以 mock 靜態方法,所以咱們可使用 Powermock
powerMock能mock靜態、final、私有方法等
PowerMock支持EasyMock和Mockito。
@RunWith(PowerMockRunner.class)
@PrepareForTest( { YourClassWithEgStaticMethod.class })
若是測試用例裏沒有使用註解@PrepareForTest,那麼能夠不用加註解@RunWith(PowerMockRunner.class),反之亦然。當你須要使用PowerMock強大功能(Mock靜態、final、私有方法等)的時候,就須要加註解@PrepareForTest。
詳見 http://blog.csdn.net/knighttools/article/details/44630975
PowerMockito.when(file.exists()).thenReturn(true);
File file = PowerMockito.mock(File.class);
ClassUnderTest underTest = new ClassUnderTest();
PowerMockito.whenNew(File.class).withArguments("bbb").thenReturn(file);
PowerMockito.when(file.exists()).thenReturn(true);
ClassDependency depencency = PowerMockito.mock(ClassDependency.class);
ClassUnderTest underTest = new ClassUnderTest();
PowerMockito.when(depencency.isAlive()).thenReturn(true);
PowerMockito.mockStatic(ClassDependency.class);
PowerMockito.when(ClassDependency.isExist()).thenReturn(true);
ClassUnderTest underTest = PowerMockito.mock(ClassUnderTest.class);
PowerMockito.when(underTest.callPrivateMethod()).thenCallRealMethod();
PowerMockito.when(underTest, "isExist").thenReturn(true);
ClassUnderTest underTest = new ClassUnderTest();
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getProperty("aaa")).thenReturn("bbb");
(1) 驗證靜態方法:
PowerMockito.verifyStatic();
Static.firstStaticMethod(param);
(2) 擴展驗證:
PowerMockito.verifyStatic(Mockito.times(2)); // 被調用2次
Static.thirdStaticMethod(Mockito.anyInt()); // 以任何整數值被調用