PowerMock 簡(jiǎn)介
要測(cè)試的方法會(huì)引用很多外部依賴的對(duì)象(獲得連接getConnection果漾,getAdmin)朴乖,外部對(duì)象不可控育灸,模擬(mock)外部對(duì)象使其可控驰后。
核心思想
你要mock的方法必須是你mock的對(duì)象調(diào)的号坡。原有的對(duì)象只會(huì)走原有的邏輯懊烤。
什么情況需要加注解:
@RunWith(PowerMockRunner.class)
@PrepareForTest ( { YourClassWithEgStaticMethod.class })
- PowerMockito.whenNew方法時(shí),注解@PrepareForTest里寫(xiě)的類(lèi)是需要mock的new對(duì)象代碼所在的類(lèi)
- 普通對(duì)象的finil方法宽堆,注解里寫(xiě)filal方法所在的類(lèi)
- 普通對(duì)象的static方法腌紧,注解里寫(xiě)static方法所在的類(lèi)
PowerMockito.mockStatic(ClassDependency.class);
PowerMockito.when(ClassDependency.isExist()).thenReturn(true);
- private方法,注解里private方法所在類(lèi)
PowerMockito.when(other.pub(Mockito.anyString())).thenCallRealMethod();
PowerMockito.when(other, "pri", Mockito.anyString()).thenReturn(" $$ I am handsome %% private.");
- 系統(tǒng)類(lèi)的靜態(tài)和final方法畜隶,注解里寫(xiě)的類(lèi)是需要調(diào)用系統(tǒng)方法所在的類(lèi)
其他
- Void方法 不用加注解壁肋,but:
PowerMockito.doNothing().when(mockUnder.dovoid(Mockito.anyString())); //WRONG
PowerMockito.doNothing().when(mockUnder).dovoid(Mockito.anyString()); //RIGHT
PowerMockito.doNothing().when(mockUnder,"dovoid","aa","bb"); //RIGHT
PowerMockito.when(mockUnder,"dovoid","aa","bb").thenAnswer(answer); //RIGHT
推薦以下的寫(xiě)法,因?yàn)槭褂梅秶容^廣
PowerMockito.doNothing().when(mockUnder,"dovoid","aa","bb");
PowerMockito.doNothing().when(UnderTest.class,"dovoid","aa","bb");
PowerMockito.when(mockUnder,"dovoid","aa","bb").thenAnswer(answer);
PowerMockito.when(under1, "isDpa", Mockito.anyString()).thenReturn(true);
- Spy
類(lèi)C的m1方法掉了m2籽慢,想覆蓋類(lèi)C的m1浸遗,模擬打樁m2
可以考慮用spy - Answer
Object[] args = invocation.getArguments();
注意傳入的參數(shù),不要越界 - 希望多次返回結(jié)果不同箱亿,比如第一次返回true跛锌,第二次false
PowerMockito.when(under1.isDpa(Mockito.anyString())).thenReturn(true).thenReturn(false);
- Mock 拋異常
PowerMockito.doThrow(new NullPointerException()).when(other).doExcep(Mockito.anyString());
拋的異常必須是mock的方法可能拋的,否則mock會(huì)拋異常
所以不要在測(cè)試用例的大catch里寫(xiě)Assert.assertTrue(true);來(lái)判斷程序拋異常届惋,因?yàn)檫@個(gè)異常很可能是mock的時(shí)候就拋了髓帽。
@Test
public void test()
{
try
{
// do some test
}
catch (Exception e)
{
e.printStackTrace();
Assert.assertTrue(false);
}
}
- 反射
UnderTest under = new UnderTest();
StudentMgr stuMgr = PowerMockito.mock(StudentMgr.class);
Class<AbstractClass> clazz = AbstractClass.class;
Field field = clazz.getDeclaredField("studentMgr");
field.setAccessible(true);
field.set(under, stuMgr);
常見(jiàn)問(wèn)題
- InitializationError
@Test 注解沒(méi)加
缺jar包
Junit 版本不對(duì)(junit不能用4.12) - spy() vs mock()
spy() is used when you want the real code of the class you are spying on to do its job, but be able to intercept method calls and return values. mock() is used to make a new class that has the same interface as the class you are mocking, but with NO code inside...
注意事項(xiàng)
- UT結(jié)束清理環(huán)境
@BeforeClass //測(cè)試class前
public static void setUpBeforeClass() throws Exception
{
}
@AfterClass //測(cè)試class前
public static void tearDownAfterClass() throws Exception
{
}
@Before //每個(gè)Test前
public void setUp() throws Exception
{
}
@After //每個(gè)Test后
public void tearDown() throws Exception
{
}
- setUp()中mock的東西會(huì)影響到每個(gè)Test
注意:
mock singleton static final : mock before other code new it.
mock單例要在其他代碼new它前
- 測(cè)試的目的
發(fā)現(xiàn)代碼的缺陷,發(fā)現(xiàn)問(wèn)題脑豹,及時(shí)與開(kāi)發(fā)確認(rèn)郑藏,不要只為了覆蓋率去寫(xiě)測(cè)試。
能全流程盡量全流程