Handler.handleMessage未在测试中调用,但在应用程序中调用 [英] Handler.handleMessage is not called in test, but is called in the app

查看:203
本文介绍了Handler.handleMessage未在测试中调用,但在应用程序中调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在单独进程中运行的服务。该服务在 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 在我的服务中。但在我的测试 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 in MyServiceTest 。您可以通过在 testStartService()方法中添加 Looper.loop()来实现MyServiceTest

  • Tie MyServiceTest to the thread on which MyService's methods are called. Write one more unit test for the component and then combine the test with MyServiceTest in one common .java test file. This will show the desired logcat output.
  • Loop the prepared Looper of InstrumentationThread in MyServiceTest. You can do it by adding Looper.loop() in the testStartService() method of MyServiceTest:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆