Android服务不是由JUnit测试启动的

m0s*_*it0 5 service junit android

我有这个测试类来测试远程服务:

public class CoreServiceBasicTest extends ServiceTestCase<CoreService> implements ServiceConnection {

    /** Tag for logging */
    private final static String TAG = CoreServiceBasicTest.class.getName();

    /** Receive incoming messages */
    private final Messenger inMessenger = new Messenger(new IncomingHandler());

    /** Communicate with the service */
    private Messenger outMessenger = null;

    /** Handler of incoming messages from service */
    private static class IncomingHandler extends Handler {

        @Override
        public void handleMessage(Message msg) {
            Log.d(TAG, "Incoming message");
        }
    }

    /** Constructor for service test */
    public CoreServiceBasicTest() {
        super(CoreService.class);
    }

    /** Start the service */
    @Override
    public void setUp() {

        // Mandatory
        try {
            super.setUp();
        } catch (Exception e) {
            e.printStackTrace();
        }

        // Start the service
        Intent service = new Intent();
        service.setClass(this.getContext(), CoreService.class);
        startService(service);
        Log.d(TAG, "Service started");
    }

    public void onServiceConnected(ComponentName className, IBinder service) {
        outMessenger = new Messenger(service);
        Log.d(TAG, "Service attached");
    }

    public void onServiceDisconnected(ComponentName className) {
        // TODO Auto-generated method stub

    }

    @SmallTest
    public void testBindService() {
        // Bind to the service
        Intent service = new Intent();
        service.setClass(getContext(), CoreService.class);
        boolean isBound = getContext().bindService(service, this, Context.BIND_AUTO_CREATE);
        assertTrue(isBound);
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是setUp()方法中的startService(service)无法正确启动服务.这是AVD显示的内容:

在此输入图像描述

如您所见,该过程已启动,但服务未启动.然后testBindService(),assertTrue(isBound)失败.

如果我从Activity启动服务,则不会发生这种情况:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Start the Core service
    Intent service = new Intent();
    service.setClass(this, CoreService.class);

    if (startService(service) == null) {
        Toast.makeText(this, "Error starting service!", Toast.LENGTH_LONG).show();
        Log.e(TAG, "Error starting service");
    } else {
        Toast.makeText(this, "Service started sucessfully", Toast.LENGTH_LONG).show();
    }

    // Die
    finish();
}
Run Code Online (Sandbox Code Playgroud)

这里服务正确启动,如下所示.

在此输入图像描述

如何启动并绑定到使用Messenger与Android测试项目中的活动进行通信的远程服务?

yor*_*rkw 11

Android测试项目(test.apk)的重点是检测应用程序项目(app.apk)并对与Application Project相关联的Android组件(活动,服务等)进行单元测试,换句话说,单元 - 测试在app.apk中创建和操作的Activity和Service.

您不应该在Test项目下的ServiceTestCase实现中第二次部分编写MessengerService实现(Messenger,IncomingHandler等).MessengerService实现只需要在Application项目的CoreService.java文件中编写一次.

ServiceConnection用于Activity和Service之间的相互通信,因为我们在这里使用ServiceTestCase(意味着单元测试服务,与其他组件的通信超出范围,因此不予考虑),我们不需要ServiceConnection实现.ServiceConnection唯一做的就是初始化一个可靠的Messenger对象,以便我们可以在以后使用,一旦正确创建了服务:

public void onServiceConnected(ComponentName className, IBinder service) {
  // This is what we want, we will call this manually in our TestCase, after calling
  // ServiceTestCase.bindService() and return the IBinder, check out code sample below.
  mService = new Messenger(service);
}
Run Code Online (Sandbox Code Playgroud)

另请注意,在这种情况下,您不需要调用ServiceTestCase.startService(),因为ServiceTestCase.bindService()将正确启动服务(如果它尚未启动)并返回我们需要用来初始化Messenger的IBinder对象对象以后.

假设您在CoreService.java中的IncomingHandler.handleMessage()实例看起来像这样:

... ...

switch (msg.what) {
  case MSG_SAY_HELLO:
    msgReceived = true;
    break;

... ...
Run Code Online (Sandbox Code Playgroud)

要测试ServiceTestCase中的发送消息功能:

... ...

IBinder messengerBinder = null;

@Override
public void setUp() throws Exception {
  super.setUp();
  // Bind the service and get a IBinder:
  messengerBinder = bindService(new Intent(this.getContext(), CoreService.class));
  //log service starting
  Log.d(TAG, "Service started and bound");
}

public void testSendMessage() {
  // Use IBinder create your Messenger, exactly what we did in ServiceConnection callback method:
  Messenger messenger = new Messenger(messengerBinder);
  Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
  messenger.send(msg);
  // Do some assert stuff here
  ... ...
}

... ...
Run Code Online (Sandbox Code Playgroud)

如果您想测试Activity和Service之间的通信,那么ServiceTestCase在这种情况下是不合适的.考虑使用ActivityInstrumentationTestCase2测试实际的Activity(它绑定到您的CoreService,这使您能够间接测试您的服务功能.


Dav*_*ser 7

只是查看ServiceTestCase文档,它说测试框架会延迟启动服务,直到你的一个测试方法调用ServiceTestCase.startService()ServiceTestCase.bindService().

查看您ServiceTestCase.startService()setUp()方法中调用的代码,而不是测试方法.这还没有启动服务.它正在等待您的一种测试方法来调用ServiceTestCase.startService()ServiceTestCase.bindService().

您的测试方法testBindService()不是调用ServiceTestCase.bindService(),而是调用Context.bindService()和失败.测试框架仍在等待,这就是服务未启动的原因.

再看一下链接的开发人员文档中的生命周期支持讨论.