簡體   English   中英

Robolectric和Retrofit - 等待回應

[英]Robolectric and Retrofit - wait for response

我想測試我的代碼是否正確地從API下載數據(使用Retrofit)並在RecyclerView中顯示它們。 為了做到這一點,我創建了一個攔截器,它嘲笑API(基於這個解決方案 )並創建了一個測試(使用Robolectric):

    @Test
    public void listLoadedCorrectlyTest() {
        MyListFragment myListFragment = new MyListFragment();
        Bundle args = new Bundle();
        FragmentTestUtil.startFragment(myListFragment);
        Robolectric.flushForegroundThreadScheduler();
        JSONArray responseArray = new JSONArray();
        try {
            responseArray = new JSONArray(ApiInterceptor.MOCK_RESPONSE);
        } catch (JSONException e) {
            Log.e("JSON", e.getMessage());
        }
        int adapterItemCount = ((RecyclerView) myListFragment.getView()
                .findViewById(R.id.rv_fruits)).getAdapter().getItemCount();
        assertThat(adapterItemCount).isEqualTo(responseArray.length());
    }

問題是測試有時會通過,有時會失敗。 我調試了代碼,我知道這是因為MyListFragment中的數據使用Retrofit的enqueue()方法加載到rv_fruits RecyclerView 我怎樣才能等待Retrofit回調,以便在數據加載到RecyclerView后檢查斷言?

Robolectric試圖使所有執行同步,因為異步代碼導致了不穩定的測試。 如果您使用像AsynTask這樣的標准內容但是改造不這樣做,這樣可以正常工作。

一種方法是隱藏一些在新線程中執行請求的Retrofit(或OkHttp)類,而不是直接執行它們。 例如, ShadowAsyncTask在主線程中執行所有runnable,而不是使用新線程,原始實現將如何執行。

另一種方法是與Espresso一起使用的IdlingResource概念。 每當您啟動一個請求時,就會在單個對象上遞增一個計數器,並在請求完成時遞減計數器。 在測試中,您可以等到計數器為零。

簡單的方法,但不好的做法將是一個簡單的睡眠。

我發現使用Robolectric和Retrofit(帶回調)的主要問題。 但是,當你如建立RestAdapterRestAdapter.Builder可以有條件地修改(NB從來沒有使用在實際應用此配置):

if(singleThreaded){
    Executor executor = Executors.newSingleThreadExecutor();
    restAdapterBuilder.setExecutors(executor, executor);
}

通過為請求和回調添加此單線程執行程序,所有測試異步代碼的標准方法(例如使用CountDownLatch )都將起作用。

另一種方法:

我一直在使用Awaitility工具取得了巨大的成功。 它與閂鎖基本相同,但更具可讀性。

在你的情況下:

@Test
public void listLoadedCorrectlyTest() {
    MyListFragment myListFragment = new MyListFragment();
    Bundle args = new Bundle();
    FragmentTestUtil.startFragment(myListFragment);
    Robolectric.flushForegroundThreadScheduler();
    JSONArray responseArray = new JSONArray();
    try {
        responseArray = new JSONArray(ApiInterceptor.MOCK_RESPONSE);
    } catch (JSONException e) {
        Log.e("JSON", e.getMessage());
    }
    int adapterItemCount = ((RecyclerView) myListFragment.getView()
            .findViewById(R.id.rv_fruits)).getAdapter().getItemCount();
    await().atMost(15, TimeUnit.SECONDS)
                      .until(responseIsSameAsCount(myListFragment, responseArray)
}


    private Callable<Boolean> responseIsSameAsCount(View myListFragment, JSONArray responseArray) {
    return new Callable<Boolean>() {
        @Override
        public Boolean call() throws Exception {
            return  ((RecyclerView) myListFragment.getView()
            .findViewById(R.id.rv_fruits)).getAdapter().getItemCount() == responseArray.length();
        }
    };
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM