Handler.handleMessage未在测试中调用,但在应用程序中调用
我有一个在单独进程中运行的服务。 该服务在onCreate()
方法中生成一个新线程。 该线程将消息发送回服务。
如果我手动启动应用程序一切正常 – Handler
在我的服务中收到消息。 但在我的测试中, handleMessage()
方法永远不会被调用。
如何修复我的测试以使handleMessage()
方法有效?
谢谢!
服务:
public class MyService extends Service { private ServiceHandler mHandler; private final int MSG_HELLO_WORLD = 1; private final String TAG = getClass().getSimpleName(); @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. return null; } @Override public void onCreate() { Log.d(TAG, "MyService.onCreate"); super.onCreate(); mHandler = new ServiceHandler(); new Thread(new Runnable() { @Override public void run() { Log.d(TAG, "Thread: run()"); while (true) { try { Log.d(TAG, "sleeping..."); Thread.sleep(3000); } catch (InterruptedException e) { Log.d(TAG, "Thread was interrupted."); break; } Log.d(TAG, "sending message..."); Message msg = Message.obtain(mHandler, MSG_HELLO_WORLD); msg.sendToTarget(); } } }).start(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "MyService.onStartCommand"); return START_REDELIVER_INTENT; } private class ServiceHandler extends Handler { @Override public void handleMessage(Message msg) { Log.d(TAG, "ServiceHandler.handleMessage"); if (msg.what == MSG_HELLO_WORLD) { Log.d(TAG, "Hello World message received!"); } } } }
测试:
public class MyServiceTest extends ServiceTestCase { private static final String TAG = MyService.class.getSimpleName(); public MyServiceTest() { super(MyService.class); } public void setUp() throws Exception { super.setUp(); } public void testStartService() throws Exception { Intent startServiceIntent = new Intent(getContext(), MyService.class); startService(startServiceIntent); MyService myService = getService(); assertNotNull(myService); // give the service some time to send messages Thread.sleep(10000); } }
App的logcat输出( handleMessage()
):
MyService.onCreate MyService.onStartCommand Thread: run() sleeping... sending message... sleeping... ServiceHandler.handleMessage Hello World message received! sending message... sleeping...
测试的logcat输出(未调用handleMessage()
):
MyService.onCreate MyService.onStartCommand Thread: run() sleeping... sending message... sleeping... sending message... sleeping... sending message... sleeping...
你的问题对我很有意思,所以我开始挖掘 。
如果我手动启动应用程序一切正常 –
Handler
在我的服务中收到消息。
使用mHandler = new ServiceHandler()
在MyService
的onCreate()
方法中初始化mHandler
时, Handler
与当前执行的线程的消息队列相关联。 mHandler
进程来自队列的Messages
,然后由循环的Looper
处理。 结果您可以看到“收到Hello World消息!” 在日志中。
但在我的测试中,
handleMessage()
方法永远不会被调用。
当您测试服务时,其方法在InstrumentationThread
上调用(请参阅Debugger
的线程),其Looper
已准备好但未循环 ,因此消息无法处理且不会显示在日志中。
如何修复我的测试以使handleMessage()方法有效?
我建议以下选项:
- 将
MyServiceTest
绑定到调用MyService
方法的线程 。 再为组件编写一个unit test
,然后将测试与MyServiceTest
结合在一个常见的.java
测试文件中。 这将显示所需的logcat
输出。 -
在
MyServiceTest
循环准备好的InstrumentationThread
Looper
。 您可以通过在MyServiceTest
的testStartService()
方法中添加Looper.loop()
来实现:public void testStartService() throws Exception { Intent startServiceIntent = new Intent(getContext(), MyService.class); startService(startServiceIntent); MyService myService = getService(); assertNotNull(myService); // Run the Looper (this call is to be added) Looper.loop(); Thread.sleep(10000); }
注意 :运行
Looper
将显示所需的logcat
输出,但测试不会因为Looper.loop()
无限期运行而停止,直到您调用Looper.quit()
。