1. 程式人生 > 其它 >MockiTo 測試用mock框架

MockiTo 測試用mock框架

引入

編寫UT測試用例時,使用mock可以只針對待測方法進行驗證,而無需考慮真實資料和呼叫方法的影響。

依賴

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

使用

參考文章:https://www.cnblogs.com/yinyunmoyi/p/14203794.html

初始化

測試類中進行UT編寫之前需要初始化MockiTo,自動建立mock物件

    @BeforeClass
    public void initMocks() throws Exception{
        System.out.println("Before Class");
        //MockitoAnnotations.initMocks(this),其中this就是單元測試所在的類,在initMocks函式中Mockito會根據類中不同的註解(如@Mock, @Spy等)建立不同的mock物件,即初始化工作
MockitoAnnotations.initMocks(this); }

@Before, @BeforeClass, @BeforeEach 和 @BeforeAll 之間的不同

特性

Junit 4 Junit 5
  • 在當前類的所有測試方法之前執行。
  • 註解在靜態方法上。
  • 此方法可以包含一些初始化程式碼。
@BeforeClass @BeforeAll
  • 在當前類中的所有測試方法之後執行。
  • 註解在靜態方法上。
  • 此方法可以包含一些清理程式碼。
@AfterClass @AfterAll
  • 在每個測試方法之前執行。
  • 註解在非靜態方法上。
  • 可以重新初始化測試方法所需要使用的類的某些屬性。
@Before @BeforeEach
  • 在每個測試方法之後執行。
  • 註解在非靜態方法上。
  • 可以回滾測試方法引起的資料庫修改。
@After

@AfterEach

 

 

 

 

 

 

 

 

 

 

 

 

標記的程式碼@Before在每次測試之前執行,而@BeforeClass在整個測試夾具之前執行一次。如果你的測試類有十個測試,則@Before程式碼將執行十次,但@BeforeClass僅執行一次。

 

通常,@BeforeClass當多個測試需要共享相同的計算昂貴的設定程式碼時,可以使用。建立資料庫連線屬於此類。你可以將程式碼從@BeforeClass移到@Before,但是測試執行可能需要更長的時間。注意,標記的程式碼@BeforeClass作為靜態初始化程式執行,因此它將在建立測試夾具的類例項之前執行。

 

-https://www.cnblogs.com/yaoyaoo/p/14344684.html

建立mock

一般使用註解方式

@InjectMocks

用它標註的類會自動裝配其中已經被在當前測試類中用 @Mock 和 @Spy 標註的欄位,該類.method(param...)是真實方法呼叫    =》該註解標記在待測類上

@Mock

建立要mock的物件,如果某個物件被 mock,那麼它將不再擁有原本的功能,全部的方法都被替換掉了,只會返回設定好的值,如果 mock 物件的某個方法沒有設定,那麼就會返回 null =》該註解標註在要mock的類上

@InjectMocks
ModelDaoImpl modelDao; 

@Mock
Mediator mediator;

...{
    // 這裡呼叫的create是真實的方法,這裡面如果有mediator呼叫某個方法,就可以通過自動裝配事先設定它的行為了
    Mockito.when(mediator.get(0)).thenReturn("foo");
    modelDao.create();
    ...
}

 

打樁(stup)

設定一類行為

有返回值

方式一:會進入方法內,只是返回值是設定的返回值

Mockito.when(A.method(param...)).thenReturn(B);

方式二:並不會進入方法內,觸發該方法就直接返回設定的值

Mockito.doReturn(C).when(A).method(B);

無返回值

返回值型別為 void的方法才能使用

doNothing().when(A.method(param...));

 

部分模擬

對於區域性變數,有時候是不好準確模擬的,即使建立一個相同的物件

如這種情況

methodA() {
Request request = new Request();

// 設定request的屬性
...

// 呼叫方法
Response response = serviceInvoker.invoke(SERVICE_NAME, request);
}

即便模擬invoke

// 建立request物件並設定其屬性
Mockito.when(serviceInvoker.invoke(SERVICE_NAME, request)).thenReturn("foo");

也是行不通的,因為在待測試的程式碼中,request 是一個區域性變數,它的地址和我們創建出來的物件地址是不同的,也就無法準確的進行模擬

解決方式可以是將生成Request的程式碼抽出來為一個方法,將該方法區域性模擬,使用spy,spy部分模擬的物件,除了設定的方法,其他的都會按照原有真實方法執行

spy:

  一,註解 @spy

  二,手動

// 使用部分模擬需要用spy方法,它必須是某個已經建立好的物件的封裝,不能用class物件為構造引數
List list = new LinkedList();
List mockedList = Mockito.spy(list);

將生成Request的程式碼抽出來為一個方法

Request request = getRequest();

// 呼叫方法
Response response = serviceInvoker.invoke(SERVICE_NAME, request);

來mock,instance是spy出來的

// 模擬getRequest方法的行為
Mockito.when(instance.getRequest()).thenReturn(request);

// 完成我們一開始想要的行為定義
Mockito.when(serviceInvoker.invoke(SERVICE_NAME, request)).thenReturn("foo");

mock靜態和私有方法

 

 

 

驗證(verify)