2014-05-02 90 views
2

我想测试下(标)的情况如何在Android JUnit测试中测试服务中的处理程序回调?

  • 的活动使用服务对象做一些东西。
  • 服务使用bindService(..)绑定到活动。
  • 服务本身允许通过一个Binder访问它,它在onBind()中返回,它可以访问服务对象本身(一切都发生在同一个线程上)。
  • 在onServiceConnected(..)中,活动通过活页夹访问服务,然后交给服务处理程序对象以将消息发送到活动。
  • 所以沟通是: 活动 - >通过服务直接调用服务。和服务 - >通过活动服务注入的处理程序对象的活动

此方案工作正常。在应用程序中没有问题。

但现在我也想写自动化的单元测试,我遇到了问题,处理程序似乎不再发送和处理消息。

我写了一个Android JUnit测试这样

public class EpcServiceMockTest extends ServiceTestCase<EpcServiceMock> {...} 

与测试方法像这样

public void testConnectToDevice() { 
    Intent serviceIntent = new Intent(getContext(), EpcServiceMock.class); 
    IBinder binder = bindService(serviceIntent); 
    EpcServiceHandlerMock mockHandler = new EpcServiceHandlerMock(this); 
    EpcServiceMock service = (EpcServiceMock) ((EpcServiceBase.LocalBinder) binder).getService(mockHandler); 
service.doSomething(..); 

这种设置工作正常。该服务运行并执行被调用的方法。但每次处理程序用于发送消息时,消息都不会执行。即HandlerMessage()永远不会在Handler上调用。

Message callbackMsg = mCallbackHandler.obtainMessage(CB_CONNECT_TO_NULL_DEVICE, mDevice); 
    mCallbackHandler.sendMessage(callbackMsg); 

该代码被调用。 Handler mCallbackHandler是正确的类型。没有错误。没有任何反应。 Handler中没有对handleMessage()的调用。

首先我认为有一个竞争条件,因为Looper是在另一个线程。所以我让测试案例睡了一会儿:

(..) 
service.doSomething(..); 
Thread.sleep(3000); 
Log.d(TAG, "Waking up ..."); 
callbacks = mockHandler.receivedCallbacks; 
assertEquals("one callback", 1, callbacks.size()); 

但是还是没有。测试场景中永远不会调用处理程序中的handleMessage()方法。但它在真实应用程序中运行良好。

在Android JUnit测试中测试处理程序时是否存在根本问题?

+0

你回答了你自己的问题,因此,请接受你自己的答案。 –

回答

0

问题解决了:

我真是太笨不启动处理程序在一个单独的线程。所以Handler和JUnit Test在同一个线程上运行。因此,JUnit首先完成,看不到处理程序的结果并失败。

当我把Handler放在不同的线程上时,JUnit测试中的一切都正常。

0

或者你可以模拟同步处理不是了Thread.sleep

Mockito.when(testHandler.post(any(Runnable.class))).thenAnswer(new Answer<Object>() { 
     @Override 
     public Object answer(InvocationOnMock invocation) throws Throwable { 
      ((Runnable) invocation.getArgument(0)).run(); 
      return null; 
     } 
    });