Handler.handleMessage未在测试中调用,但在应用程序中调用 [英] Handler.handleMessage is not called in test, but is called in the app
问题描述
我有一个在单独进程中运行的服务。该服务在 onCreate()
方法中生成一个新线程。该线程将消息发送回服务。
I have a service that runs in a separate process. The service spawns a new thread in onCreate()
method. This thread sends messages back to the service.
如果我手动启动应用程序一切正常 - 消息由 Handler $ c收到$ c>在我的服务中。但在我的测试
handleMessage()
方法永远不会被调用。
If I start the app manually everything works fine - messages are received by the Handler
in my service. But in my test handleMessage()
method is never get called.
如何修复我的测试以使 handleMessage()
方法工作?
How can I fix my test to make handleMessage()
method work?
谢谢!
服务:
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<MyService> {
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);
}
}
应用程序的logcat输出( handleMessage ()
被调用):
App's logcat output (handleMessage()
is called):
MyService.onCreate
MyService.onStartCommand
Thread: run()
sleeping...
sending message...
sleeping...
ServiceHandler.handleMessage
Hello World message received!
sending message...
sleeping...
测试的logcat输出( handleMessage()
未被调用):
Test's logcat output (handleMessage()
is not called):
MyService.onCreate
MyService.onStartCommand
Thread: run()
sleeping...
sending message...
sleeping...
sending message...
sleeping...
sending message...
sleeping...
推荐答案
你的问题对我来说似乎很有趣,所以我开始挖掘。
如果我手动启动应用程序一切正常 - 我的服务中的
处理程序
会收到消息。
在 MyService
的中初始化
方法 mHandler
时onCreate() mHandler = new ServiceHandler()
, Handler
是与当前执行的线程的消息队列相关联。 mHandler
处理 <$ c来自队列的$ c>消息 ,反过来由 Looper
正在循环 。结果你可以在日志中看到收到Hello World消息!。
When you initialize mHandler
in the MyService
's onCreate()
method with mHandler = new ServiceHandler()
, the Handler
is associated with the message queue of the currently executed thread. mHandler
process Messages
from the queue that, in its turn, is handled by Looper
which is looping. As the result you can see "Hello World message received!" in logs.
但是在我的测试中
handleMessage()
方法永远不会被调用。
But in my test
handleMessage()
method is never get called.
当你测试服务时方法在 InstrumentationThread
上调用(参见 Debugger
中的线程),其 Looper
准备好了但没有循环,因此消息无法处理,也不会显示在日志中。
When you test the service its methods are called on InstrumentationThread
(see the threads in Debugger
) whose Looper
is prepared but not looping, so the messages can't be handled and aren't shown in logs.
如何修复测试使handleMessage()方法有效吗?
How can I fix my test to make handleMessage() method work?
我建议使用以下选项:
- 将
MyServiceTest
绑定到MyService
的方法称为 。为组件再写一次单元测试
,然后将测试与MyServiceTest
组合在一个常见的中.java
测试文件。这将显示所需的logcat
输出。 -
循环准备好的
Looper
InstrumentationThread
inMyServiceTest
。您可以通过在的
:testStartService()
方法中添加Looper.loop()
来实现MyServiceTest
- Tie
MyServiceTest
to the thread on whichMyService
's methods are called. Write one moreunit test
for the component and then combine the test withMyServiceTest
in one common.java
test file. This will show the desiredlogcat
output. Loop the prepared
Looper
ofInstrumentationThread
inMyServiceTest
. You can do it by addingLooper.loop()
in thetestStartService()
method ofMyServiceTest
:
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()<,测试不会停止/ code>无限期运行,直到您致电
Looper.quit()
。
Note: running the Looper
will show the desired logcat
output, but the test won't stop because of Looper.loop()
running indefinitely until you call Looper.quit()
.
这篇关于Handler.handleMessage未在测试中调用,但在应用程序中调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!