1. 引言
在進行單元測試時,經常遇到被測方法依賴外部對象和環境,如需要數據庫連接,網絡通信依賴等,需要進行大量的初始化工作,這時可以采用powermock+mockito對被測對象進行模擬,通過錄放的形式解決此類問題。
Mockito 是一個針對 Java 的單元測試模擬框架,它與 EasyMock 和 jMock 很相似,都是為了簡化單元測試過程中測試上下文 ( 或者稱之為測試驅動函數以及樁函數 ) 的搭建而開發的工具。
PowerMock 也是一個單元測試模擬框架,它是在其它單元測試模擬框架的基礎上做出的擴展。通過提供定制的類加載器以及一些字節碼篡改技巧的應用,PowerMock 現了對靜態方法、構造方法、私有方法以及 Final 方法的模擬支持,對靜態初始化過程的移除等強大的功能。
2. 使用實例
模擬接口返回
首先對接口進行mock,然后錄制相關行為
InterfaceToMock mock = Powermockito.mock(InterfaceToMock.class)
Powermockito.when(mock.method(Params…)).thenReturn(value)
Powermockito.when(mock.method(Params..)).thenThrow(Exception)
設置對象的private屬性
需要使用whitebox向class或者對象中賦值。
如我們已經對接口盡心了mock,現在需要將此mock加入到對象中,可以采用如下方法:
Whitebox.setInternalState(Object object, String fieldname, Object… value);
其中object為需要設置屬性的靜態類或對象。
模擬構造函數
注意解決出現的@PowerMockIgnore("javax.management.*")問題
對於模擬構造函數,也即當出現new InstanceClass()時可以將此構造函數攔截並替換結果為我們需要的mock對象。
注意:使用時需要加入標記:
@RunWith(PowerMockRunner.class)
@PrepareForTest({ InstanceClass.class })
@PowerMockIgnore("javax.management.*")
Powermockito.whenNew(InstanceClass.class).thenReturn(Object value)
模擬靜態方法
模擬靜態方法類似於模擬構造函數,也需要加入注釋標記。
@RunWith(PowerMockRunner.class)
@PrepareForTest({ StaticClassToMock.class })
@PowerMockIgnore("javax.management.*")
Powermockito.mockStatic(StaticClassToMock.class);
Powermockito.when(StaticClassToMock.method(Object.. params)).thenReturn(Object value)
模擬final方法
Final方法的模擬類似於模擬靜態方法。
@RunWith(PowerMockRunner.class)
@PrepareForTest({ FinalClassToMock.class })
@PowerMockIgnore("javax.management.*")
Powermockito.mockStatic(FinalClassToMock.class);
Powermockito.when(StaticClassToMock.method(Object.. params)).thenReturn(Object value)
模擬靜態類
模擬靜態類類似於模擬靜態方法。
使用spy方法避免執行被測類中的成員函數
如被測試類為:TargetClass,想要屏蔽的方法為targetMethod.
1) PowerMockito.spy(TargetClass.class);
2) Powemockito.when(TargetClass.targetMethod()).doReturn()
3) 注意加入
@RunWith(PowerMockRunner.class)
@PrepareForTest(DisplayMoRelationBuilder.class)
@PowerMockIgnore("javax.management.*")
參數匹配器
有時我們在處理doMethod(Param param)時,不想進行精確匹配,這時可以使用Mockito提供的模糊匹配方式。
如:
Mockito.anyInt(),Mockito.anyString()
處理public void型的靜態方法
Powermockito.doNothing.when(T class2mock, String method, <T>… params>
3.常見問題
使用Powermock后會提示classloader錯誤
加入注解:
@PowerMockIgnore("javax.management.*")
Eclipse + junit4 + Emma 無法統計覆蓋率情況
Emma問題導致,暫無處理方法。
使用Ant和HUTAF_LLT覆蓋率插件出現的覆蓋率無法統計情況
原因是對被統計類使用了PrepareForTest()注解,去掉該注解,不再進行被測類方法進行mock.