1. 程式人生 > >Mock單元測試

Mock單元測試

多次調用 註入 tor call stream exceptio system ive eth

  單元測試的思路是在不涉及依賴的情況下測試代碼,一般是測試service層的方法,但實際的代碼常會涉及到依賴,一個可行的方法就是使用模擬對象來替換依賴對象。

1.使用Mockito生成mock對象

  Mockito 是一個流行 mock 框架,可以和JUnit結合起來使用。Mockito 允許你創建和配置 mock 對象。使用Mockito可以明顯的簡化對外部依賴的測試類的開發。

一般使用 Mockito 需要執行下面三步

  • 模擬並替換測試代碼中外部依賴。

  • 執行測試代碼

  • 驗證測試代碼是否被正確的執行

1.1.在maven中添加mockito依賴

        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <scope>test</scope>
        </dependency>

1.2.靜態引用

如果在代碼中靜態引用了org.mockito.Mockito.*;,那你你就可以直接調用靜態方法和靜態變量而不用創建對象,譬如直接調用 mock() 方法。

1.3.使用 Mockito 創建和配置 mock 對象

Mockito 還支持通過 @Mock 註解的方式來創建 mock 對象

使用註解,那麽必須要實例化 mock 對象。Mockito 在遇到使用註解的字段的時候,會調用MockitoAnnotations.initMocks(this) 來初始化該 mock 對象。另外也可以通過使用@RunWith(MockitoJUnitRunner.class)來達到相同的效果。

註解

  • @Mock:創建 mock 對象
  • @InjectMocks 在 Mockito 中進行依賴註入

調用方法

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)

驗證 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");

1.4.mockito的限制

下面三種數據類型則不能夠被測試

  • final classes

  • anonymous classes

  • primitive types

Mockito 不能夠 mock 靜態方法,因此我們可以使用 Powermock

2.powerMock

powerMock能mock靜態、final、私有方法等

PowerMock支持EasyMock和Mockito。

2.1PowerMock有兩個重要的註解:
[email protected](PowerMockRunner.class)
[email protected]( { YourClassWithEgStaticMethod.class })
[email protected]t,[email protected](PowerMockRunner.class),反之亦然。當你需要使用PowerMock強大功能(Mock靜態、final、私有方法等)的時候,就需要加註解

@PrepareForTest。

2.2基本用法

詳見 http://blog.csdn.net/knighttools/article/details/44630975

2.2.1和普通Mock的用法相同

PowerMockito.when(file.exists()).thenReturn(true);

2.2.2 Mock方法內部new出來的對象

File file = PowerMockito.mock(File.class);
ClassUnderTest underTest = new ClassUnderTest();
PowerMockito.whenNew(File.class).withArguments("bbb").thenReturn(file);
PowerMockito.when(file.exists()).thenReturn(true);

2.2.3 Mock普通對象的final方法

ClassDependency depencency = PowerMockito.mock(ClassDependency.class);
ClassUnderTest underTest = new ClassUnderTest();
PowerMockito.when(depencency.isAlive()).thenReturn(true);

2.2.4.Mock普通類的靜態方法

PowerMockito.mockStatic(ClassDependency.class);
PowerMockito.when(ClassDependency.isExist()).thenReturn(true);

2.2.5 Mock 私有方法

ClassUnderTest underTest = PowerMockito.mock(ClassUnderTest.class);
PowerMockito.when(underTest.callPrivateMethod()).thenCallRealMethod();
PowerMockito.when(underTest, "isExist").thenReturn(true);

2.2.6. Mock系統類的靜態和final方法

ClassUnderTest underTest = new ClassUnderTest();
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getProperty("aaa")).thenReturn("bbb");

2.2.7 驗證方法

(1) 驗證靜態方法:
PowerMockito.verifyStatic();
Static.firstStaticMethod(param);
(2) 擴展驗證:
PowerMockito.verifyStatic(Mockito.times(2)); // 被調用2次

Static.thirdStaticMethod(Mockito.anyInt()); // 以任何整數值被調用

Mock單元測試