PowerMock中對java接口進行測試


最近在對自己的項目寫一些單元測試,選擇了Powermock測試框架。

關於Powermock的使用網上有很多例子,這里不再介紹。但是開發代碼中有很多地方使用了接口,搜了百度和谷歌都沒有找到解決辦法。

如題,這里介紹使用Powermock對接口進行測試的一種方法,特做記錄。

待測試類和方法:這里以流行的OkHttpClient網絡請求接口Callback為例

public class DownloadResource {

    public void downloadResource(String url){
        url += "/";
        Callback callback = new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                System.out.print("onFailure");
                //do something.
                doOtherMethod(false);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                System.out.print("onResponse");
                //do something.
                doOtherMethod(true);
            }
        };
        //從緩存中獲取一個httpClient實例
        OkHttpClient httpClient = PafPluginCache.getInstance().getHttpClient();
        Request request = new Request.Builder().url(url).get().build();
        httpClient.newCall(request).enqueue(callback);
    }

    private void doOtherMethod(boolean b) {

    }
}

對應的測試類:

@RunWith(PowerMockRunner.class)
@PrepareForTest({DownloadResource.class, PafPluginCache.class})
public class DownloadResourceTest {

    @Test
    public void downloadResource() throws Exception {
        DownloadResource downloadResource = new DownloadResource();
        DownloadResource spy = spy(downloadResource);

        OkHttpClient okHttpClient = mock(OkHttpClient.class);
        PafPluginCache pafPluginCache = mock(PafPluginCache.class);
        mockStatic(PafPluginCache.class);
        when(PafPluginCache.getInstance()).thenReturn(pafPluginCache);
        when(pafPluginCache.getHttpClient()).thenReturn(okHttpClient);

        Request.Builder builder = mock(Request.Builder.class);
        when(builder.url(anyString())).thenReturn(builder);
        when(builder.get()).thenReturn(builder);

        Call call = mock(Call.class);
        when(okHttpClient.newCall(any(Request.class))).thenReturn(call);
        //替換mock的method的實現
        doAnswer(new Answer() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                Object[] args = invocation.getArguments();
                System.out.print("proxy:" + invocation.getMock() + "\n");
                System.out.print("invoke(" + args[0] + /*", " + args[1] +*/ ")\n");
                Object o1 = args[0];
                if(o1 instanceof Callback){
                    Callback callback = (Callback) o1;
                    callback.onResponse(null, null);
                }
                return null;
            }
        }).when(call).enqueue(any(Callback.class));

        spy.downloadResource("http://www.abc.com");
        verifyPrivate(spy, times(1)).invoke("doOtherMethod", true);
    }
}

執行測試用例的結果:

簡單總結一下原理,利用doAnswer方法獲取到被測類中被測方法的入參,其中一個入參就是接口的實例DownloadResource$1@4a83a74a。然后我們就可以調用該接口實例的方法了。

 

另外,准備了一些對於Powermock的使用的個人經驗,如有錯誤,歡迎指正。

  1. 通過mock(class)得到的mock對象,其所有非靜態方法和域都是虛假的,如果要使用這些方法和域,需要先進行設置
  2. mockStatic(class)后,該類的所有靜態方法和靜態域都是虛假的,且需要加入到@PrepareForTest中,如果要使用這些方法和域,需要先進行設置
  3. android包下的所有類都自動被mock了,且無法通過callRealMethod方法使其真實,也包括org.json下的類。
  4. spy(object)中入參應為真實對象,和mock對象相反,其所有非靜態方法和域都是真實的,可以對某個方法進行mock設置
  5. 使用verify系列方法可以驗證mock對象和spy對象的方法執行次數
  6. 設置when系列方法進行mock條件時,可以傳入具體值或者模糊值,但是同時傳入具體值和模糊值時,具體值需要使用eq方法包裝一下。調用方法時不可傳入模糊值
  7. reset(mock)方法可以重置所有mock條件和verify系列方法的驗證次數
  8. 調用私有方法可以使用Whitebox.invokeMethod系列方法
  9. suppress方法可以跳過任意一個方法,一般測試子類時,禁用父類方法。
  10. 使用inOrder方法來驗證mock對象的調用順序

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM