【问题标题】:How to test Handler callbacks from a Service in an Android JUnit Test?如何在 Android JUnit 测试中测试来自服务的处理程序回调?
【发布时间】:2014-05-02 15:27:06
【问题描述】:

我想测试以下(标准?)场景

  • 一个活动使用一个服务对象来做一些事情。
  • Service 使用 bindService(..) 绑定到 Activity。
  • 服务本身允许通过它在 onBind() 中返回的 Binder 进行访问,该 Binder 提供对服务对象本身的访问(这里的一切都发生在同一个线程上)。
  • 在 onServiceConnected(..) 中,活动通过 Binder 访问服务并将处理程序对象交给服务以向活动发送消息。
  • 所以通讯是: 活动 -> 通过直接调用服务的服务。和 Service -> Activity 通过 Handler 对象从 Activity 注入到 Service 中

此方案运行良好。应用程序没有问题。

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

我这样写了一个 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(..);

此设置运行良好。该服务运行并执行调用的方法。但是每次处理程序用于发送消息时,消息永远不会被执行。即,handleMessage() 永远不会在 Handler 上调用。

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

调用此代码。处理程序 mCallbackHandler 是正确的类型。没有错误。只是什么都没有发生。处理程序中没有调用handleMessage()。

首先我认为存在竞争条件,因为 Looper 在另一个线程上。所以我让测试用例休眠了一会儿:

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

但还是一无所获。处理程序中的 handleMessage() 方法永远不会在测试场景中被调用。但在真正的 App 中运行良好。

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

【问题讨论】:

  • 您回答了自己的问题,所以请接受您自己的回答。

标签: java android unit-testing junit handler


【解决方案1】:

或者你可以模拟同步处理程序而不是 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;
        }
    });

【讨论】:

    【解决方案2】:

    问题解决了:

    我太愚蠢了,没有在单独的线程上启动处理程序。因此,处理程序与 JUnit 测试在同一线程上运行。因此,JUnit 首先完成,看不到 Handler 的任何结果并失败。

    当我将处理程序放在不同的线程上时,JUnit 测试中一切正常。

    【讨论】:

      猜你喜欢
      • 2021-12-15
      • 2015-02-19
      • 2017-07-26
      • 2011-02-26
      • 2013-06-30
      • 1970-01-01
      • 1970-01-01
      • 2016-05-15
      • 1970-01-01
      相关资源
      最近更新 更多