【问题标题】:Handler.handleMessage is not called in test, but is called in the appHandler.handleMessage 在测试中没有被调用,而是在app中被调用
【发布时间】:2014-09-08 11:55:18
【问题描述】:

我有一个在单独进程中运行的服务。该服务在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<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);
    }
}

App的logcat输出(handleMessage()被调用):

MyService.onCreate
MyService.onStartCommand
Thread: run()
sleeping...
sending message...
sleeping...
ServiceHandler.handleMessage
Hello World message received!
sending message...
sleeping...

Test 的 logcat 输出(handleMessage() 未被调用):

MyService.onCreate
MyService.onStartCommand
Thread: run()
sleeping...
sending message...
sleeping...
sending message...
sleeping...
sending message...
sleeping...

【问题讨论】:

    标签: java android android-service android-testing android-handler


    【解决方案1】:

    我觉得你的问题很有趣,所以我开始挖掘

    如果我手动启动应用程序,一切正常 - 我的服务中的 Handler 会收到消息。

    当您在MyServiceonCreate() 方法中使用mHandler = new ServiceHandler() 初始化mHandler 时,Handler 与当前执行线程的消息队列相关联。 mHandler 处理来自队列的Messages,而队列又由Looper 处理,其中is looping。结果,您可以在日志中看到 “收到 Hello World 消息!”

    但在我的测试中,handleMessage() 方法永远不会被调用。

    当您测试服务时,它的方法在 InstrumentationThread 上调用(请参阅 Debugger 中的线程),其 Looperprepared不循环,因此消息不能被处理并且不显示在日志中。

    如何修复我的测试以使 handleMessage() 方法正常工作?

    我建议以下选项:

    • MyServiceTest 绑定到调用MyService 方法的线程。为组件再写一个unit test,然后将测试与MyServiceTest 合并到一个通用的.java 测试文件中。这将显示所需的logcat 输出。
    • MyServiceTest中循环InstrumentationThread中准备好的Looper。您可以通过在MyServiceTesttestStartService() 方法中添加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()

    【讨论】:

      猜你喜欢
      • 2019-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-02
      • 2021-09-15
      • 2020-05-11
      • 1970-01-01
      • 2016-02-23
      相关资源
      最近更新 更多