我有这个测试类来测试远程服务:
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);
}
}
问题是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();
}
此处服务正确启动,如下所示。
如何启动并绑定到使用Messenger与Android测试项目中的活动进行通信的远程服务?
答案 0 :(得分:11)
Android Test Project(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);
}
另请注意,在这种情况下,您不需要调用ServiceTestCase.startService(),因为ServiceTestCase.bindService()将正确启动服务(如果尚未启动)并返回我们需要使用的IBinder对象稍后初始化Messenger对象。
假设您在CoreService.java中的IncomingHandler.handleMessage()实例看起来像这样:
... ...
switch (msg.what) {
case MSG_SAY_HELLO:
msgReceived = true;
break;
... ...
测试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
... ...
}
... ...
如果您想测试Activity和Service之间的通信,那么ServiceTestCase在这种情况下是不合适的。考虑使用ActivityInstrumentationTestCase2测试实际的Activity(绑定到您的CoreService,这使您能够间接测试您的服务功能。
答案 1 :(得分:7)
只看documentation for ServiceTestCase它说测试框架延迟启动服务,直到您的某个测试方法调用ServiceTestCase.startService()
或ServiceTestCase.bindService()
。
查看代码,在ServiceTestCase.startService()
方法中调用setUp()
,不在测试方法中。这还没有启动服务。它正在等待您的一种测试方法来调用ServiceTestCase.startService()
或ServiceTestCase.bindService()
。
您的测试方法testBindService()
未调用ServiceTestCase.bindService()
,而是调用Context.bindService()
并失败。测试框架仍在等待,这就是服务未启动的原因。
再次查看链接的开发人员文档中的生命周期支持讨论。