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...)是真實方法呼叫 =》該註解標記在待測類上
@InjectMocks ModelDaoImpl modelDao; @Mock Mediator mediator; ...{ // 這裡呼叫的create是真實的方法,這裡面如果有mediator呼叫某個方法,就可以通過自動裝配事先設定它的行為了 Mockito.when(mediator.get(0)).thenReturn("foo"); modelDao.create(); ... }
設定一類行為
有返回值
方式一:會進入方法內,只是返回值是設定的返回值
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)