2012-08-12 265 views
6

我是新的Android測試,我想測試一個IntentService,我目前正在擴展ServiceTestCase。如何JUnit測試IntentService

我試圖使用ResultReceiver,但問題是OnReceiveResult永遠不會在測試用例中調用。 (我也嘗試創建ResultReceivernew Handler()作爲null參數insetad,但具有相同的結果。

我究竟做錯了什麼? 什麼是測試一個IntentService

這是服務的正確方法:

public class MyService extends IntentService { 

public MyService() { 
    super("MyService"); 
} 

public MyService(String name) { 
    super(name); 
} 

@Override 
protected void onHandleIntent(Intent intent) { 
    final int action = intent.getIntExtra("action", 0); 
    final int request = intent.getIntExtra("request", 0); 
    final ResultReceiver receiver = (ResultReceiver) intent.getExtras().get("receiver"); 

    if (receiver == null) { 
     return; 
    } 

    if (action == 0 || request == 0) { 
     receiver.send(0, null); 

     return; 
    } 
} 

}

,這是測試:

public void testHandleInvalidRequests() { 
    ResultReceiver receiver = new ResultReceiver(null) { 
     @Override 
     protected void onReceiveResult(int resultCode, Bundle resultData) { 
      fail(); 
     } 
    }; 

    Intent intent = new Intent(mContext, MyService.class); 
    intent.putExtra("receiver", receiver); 
    startService(intent); 

} 

回答

4

我成功設法測試了我的IntentService,我將從概念上向您展示我是如何做到的。

首先,您擴展了Android服務測試類:ServiceTestCase<MyIntentService>。然後,您基本上開始IntentService,就像您使用startService(intent)一樣。

由於被測服務是一個IntentService,它將完成所有在產生工作線程中的工作。如果你不阻止你的測試線程,那麼你的測試方法會立即做出斷言,這顯然會失敗,因爲後臺的測試工作可能還沒有完成。最終,測試方法將返回並且您的測試將失敗。

你需要做的是在startService之後屏蔽你的測試線程。使用ReentrantLock以及調用await()的條件來執行此操作。

IntentService然後在後臺執行onHandleIntent。我建議你擴展你的IntentService並覆蓋onHandleIntent,調用super.onHandleIntent(),然後告訴你的測試線程已完成工作。在用於阻塞測試線程的相同鎖和條件下執行此操作。

+1

你能給這裏使用一個ReentrantLock的例子嗎? – 2015-01-29 23:22:41

+0

我也會非常感興趣的例子(甚至兩年後)。謝謝。 – JDenais 2015-02-10 03:00:47

+0

嗨,我用來初始化意圖的任何上下文似乎拋出一個空指針異常。你是如何設定你的環境的? – kyrax 2016-04-18 15:43:31

0

如果startService()在測試文件擴展ServiceTestCase<>,我在Android Studio中1.1的測試設備已經發現,ServiceTestCase不會通過onHandleIntent()實例化一個IntentService對象。
有關更多信息,請參閱Android ServiceTestCase for IntentService

0

我知道這是舊的,但由於我有同樣的問題,我會在這裏發佈我如何最終成功地在IntentService上運行測試。正如@Joerg所說,這是一個線程問題。

public class MyServiceTest extends ServiceTestCase<MyService> { 
    public MyServiceTest() { 
     super(MyService.class); 
    } 

    public void testOnHandleIntent() throws Exception { 
     Looper.prepare(); 
     final CountDownLatch latch = new CountDownLatch(1); 

     ResultReceiver receiver = new ResultReceiver(new Handler()) { 
      @Override 
      protected void onReceiveResult(int resultCode, Bundle resultData) { 
       latch.countDown(); 

       assertEquals(resultCode, 0); 
       assertNull(resultData); 
       fail(); 

       Looper.myLooper().quit(); 
      } 
     }; 

     Intent intent = new Intent(getSystemContext(), MyService.class); 
     intent.putExtra("receiver", receiver); 
     getSystemContext().startService(intent); 

     Looper.loop(); 

     assertThat(latch.getCount(), is(0L)); 
    } 
} 

LooperHandler類是必要的,這樣的回調有一個線程中調用的。鎖存器只是作爲鎖的一個例子,並且作爲在測試方法結束之前斷言回調傳遞的代碼的一種手段。

如果沒有調用Looperquit()方法,則測試掛起。

ServiceTestCase不贊成在Android的最新版本,但更換(ServiceTestRule)不支持IntentService ...