2017-04-24 64 views
1

我試圖測試我的網絡模塊。當我在模擬器或設備上運行它時,處理程序是可以的,但是當我試圖從測試中執行時,handler = null和callback不會被調用。我怎麼解決這個問題?在使用junit測試期間Android Handler爲null

public void performCall(Call callToPerform){ 
    callToPerform.call.enqueue(new okhttp3.Callback() { 
     Handler handler = new Handler(); 

     @Override 
     public void onFailure(okhttp3.Call call, IOException e) { 
      handler.post(() -> { 
       for (Callback callback : callToPerform.callbacks) { 
        callback.onFailure(callToPerform, e); 
       } 
      }); 
     } 

     @Override 
     public void onResponse(okhttp3.Call call, final okhttp3.Response response){ 
      handler.post(() -> { 
       for (Callback callback : callToPerform.callbacks) { 
        try { 
         callback.onResponse(callToPerform, new Response(response.body().bytes(), response.headers().toMultimap())); 
        } catch (IOException e) { 
         callback.onFailure(call, e); 
        } 
       } 
      }); 
     } 
    }); 
} 

我的分級應用程序文件包含此參數。

testOptions { 
    unitTests.returnDefaultValues = true 
} 

回答

0

好吧,研究了幾個小時後,我找到了解決方案,它類似於this

package com.dpmedeiros.androidtestsupportlibrary; 

import android.os.Handler; 
import android.os.Looper; 

import org.mockito.invocation.InvocationOnMock; 
import org.mockito.stubbing.Answer; 
import org.powermock.api.mockito.PowerMockito; 

import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.TimeUnit; 

import static org.mockito.Mockito.*; 

/** 
* Utility methods that unit tests can use to do common android library mocking that might be needed. 
*/ 
public class AndroidMockUtil { 

    private AndroidMockUtil() {} 
    /** 
    * Mocks main thread handler post() and postDelayed() for use in Android unit tests 
    * 
    * To use this: 
    * <ol> 
    *  <li>Call this method in an {@literal @}Before method of your test.</li> 
    *  <li>Place Looper.class in the {@literal @}PrepareForTest annotation before your test class.</li> 
    *  <li>any class under test that needs to call {@code new Handler(Looper.getMainLooper())} should be placed 
    *  in the {@literal @}PrepareForTest annotation as well.</li> 
    * </ol> 
    * 
    * @throws Exception 
    */ 
    public static void mockMainThreadHandler() throws Exception { 
     PowerMockito.mockStatic(Looper.class); 
     Looper mockMainThreadLooper = mock(Looper.class); 
     when(Looper.getMainLooper()).thenReturn(mockMainThreadLooper); 
     Handler mockMainThreadHandler = mock(Handler.class); 
     Answer<Boolean> handlerPostAnswer = new Answer<Boolean>() { 
      @Override 
      public Boolean answer(InvocationOnMock invocation) throws Throwable { 
       Runnable runnable = invocation.getArgumentAt(0, Runnable.class); 
       Long delay = 0L; 
       if (invocation.getArguments().length > 1) { 
        delay = invocation.getArgumentAt(1, Long.class); 
       } 
       if (runnable != null) { 
        mainThread.schedule(runnable, delay, TimeUnit.MILLISECONDS); 
       } 
       return true; 
      } 
     }; 
     doAnswer(handlerPostAnswer).when(mockMainThreadHandler).post(any(Runnable.class)); 
     doAnswer(handlerPostAnswer).when(mockMainThreadHandler).postDelayed(any(Runnable.class), anyLong()); 
     PowerMockito.whenNew(Handler.class).withArguments(mockMainThreadLooper).thenReturn(mockMainThreadHandler); 
    } 

    private final static ScheduledExecutorService mainThread = Executors.newSingleThreadScheduledExecutor(); 

} 
1

如果運行JUnit的此示例代碼,這是行不通的,因爲JUnit測試是在JVM上運行,並且儀器化測試是在一個仿真或真實設備運行

你可以看看這個環節,它解釋了原因:

Instrumented tests or Local tests

+0

好文章,謝謝! – quaddef