UT和PowerMock

PowerMock 簡介

要測試的方法會引用很多外部依賴的對象(獲得連接getConnection,getAdmin),外部對象不可控,模擬(mock)外部對象使其可控。

核心思想

你要mock的方法必須是你mock的對象調的。原有的對象只會走原有的邏輯。

什么情況需要加注解:

@RunWith(PowerMockRunner.class)
@PrepareForTest ( { YourClassWithEgStaticMethod.class })
  1. PowerMockito.whenNew方法時,注解@PrepareForTest里寫的類是需要mock的new對象代碼所在的類
  2. 普通對象的finil方法,注解里寫filal方法所在的類
  3. 普通對象的static方法,注解里寫static方法所在的類
PowerMockito.mockStatic(ClassDependency.class);
PowerMockito.when(ClassDependency.isExist()).thenReturn(true);
  1. private方法,注解里private方法所在類
PowerMockito.when(other.pub(Mockito.anyString())).thenCallRealMethod();
PowerMockito.when(other, "pri", Mockito.anyString()).thenReturn(" $$ I am handsome %% private.");
  1. 系統類的靜態和final方法,注解里寫的類是需要調用系統方法所在的類

其他

  1. 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

推薦以下的寫法,因為使用范圍比較廣

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);
  1. Spy
    類C的m1方法掉了m2,想覆蓋類C的m1,模擬打樁m2
    可以考慮用spy
  2. Answer
    Object[] args = invocation.getArguments();
    注意傳入的參數,不要越界
  3. 希望多次返回結果不同,比如第一次返回true,第二次false
    PowerMockito.when(under1.isDpa(Mockito.anyString())).thenReturn(true).thenReturn(false);
  4. Mock 拋異常
    PowerMockito.doThrow(new NullPointerException()).when(other).doExcep(Mockito.anyString());
    拋的異常必須是mock的方法可能拋的,否則mock會拋異常
    所以不要在測試用例的大catch里寫Assert.assertTrue(true);來判斷程序拋異常,因為這個異常很可能是mock的時候就拋了。
    @Test
    public void test() 
    {
        try
        {
            // do some test
        }
        catch (Exception e)
        {
            e.printStackTrace();
            Assert.assertTrue(false);
        }
    }
  1. 反射
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);

常見問題

  1. InitializationError
    @Test 注解沒加
    缺jar包
    Junit 版本不對(junit不能用4.12)
  2. 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...

注意事項

  1. UT結束清理環境
    @BeforeClass        //測試class前
    public static void setUpBeforeClass() throws Exception
    {
    }
    @AfterClass     //測試class前
    public static void tearDownAfterClass() throws Exception
    {
    }
    @Before     //每個Test前
    public void setUp() throws Exception
    {
    }
    @After      //每個Test后
    public void tearDown() throws Exception
    {
    }
  1. setUp()中mock的東西會影響到每個Test
    注意:

mock singleton static final : mock before other code new it.
mock單例要在其他代碼new它前

  1. 測試的目的
    發現代碼的缺陷,發現問題,及時與開發確認,不要只為了覆蓋率去寫測試。
    能全流程盡量全流程
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,523評論 25 708
  • 本文介紹了Android單元測試入門所需了解的內容,包括JUnit、Mockito和PowerMock的使用,怎樣...
    于衛國閱讀 4,623評論 0 5
  • Instrumentation介紹 Instrumentation是個什么東西? Instrumentation測...
    打不死的小強qz閱讀 7,823評論 2 39
  • 背景 在寫單元測試的過程中,一個很普遍的問題是,要測試的目標類會有很多依賴,這些依賴的類/對象/資源又會有別的依賴...
    johnnycmj閱讀 1,189評論 0 3
  • 跋山涉水做了四個半小時的車程來到了美麗的山城,心情確并不美麗,開會加班,晚上只睡了一個半小時,點了杯美美的冰飲,不...
    Universe_Eva閱讀 243評論 0 0