2012-08-12 230 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 ...