Android 如何使用Robolectric测试IntentService?
我正在尝试使用Android 如何使用Robolectric测试IntentService?,android,android-testing,robolectric,Android,Android Testing,Robolectric,我正在尝试使用roblectric测试IntentService的onHandleIntent()方法 我以以下方式开始服务: Activity activity = new Activity(); Intent intent = new Intent(activity, MyService.class); activity.startService(intent); ShadowActivity shadowActivity = Robolectric.shadowOf(activity);
roblectric
测试IntentService
的onHandleIntent()
方法
我以以下方式开始服务:
Activity activity = new Activity();
Intent intent = new Intent(activity, MyService.class);
activity.startService(intent);
ShadowActivity shadowActivity = Robolectric.shadowOf(activity);
Intent startedIntent = shadowActivity.getNextStartedService();
assertNotNull(startedIntent);
似乎startedIntent
不为null,但似乎未调用onHandleIntent()
我应该如何测试它呢?我认为你的方法是错误的。 您正在这里测试:
Intent startedIntent = shadowActivity.getNextStartedService();
assertNotNull(startedIntent);
调用了startService()
然后,您必须假设Android已经正确地实现了他们的目的,并且在调用startService()
之后,服务确实会启动
我认为如果你想测试onHandleIntent()
的行为,你必须直接调用它
我不太清楚。。。但我认为你想写的测试只是测试Android框架。您应该编写两个测试
1) 测试是否调用了startService()
2) 测试onHandleIntent()
的行为(直接调用它)
我对机器人分子
几乎没有经验,但希望这会有所帮助
CheersOnHandleContent
是一个受保护的方法,因此不能直接调用
我的解决方案是在我的测试用例中扩展服务类,覆盖onHandleIntent
使其公开并调用super.onHandleIntent(intent)
然后直接从测试用例调用onHandleIntent
。我使用这个
@Before
public void setup(){
mainActivity = Robolectric.buildActivity(MainActivity.class)
.create()
.start()
.resume()
.get();
context = Robolectric.getShadowApplication().getApplicationContext();
bt_start = (Button) mainActivity.findViewById(R.id.button);
bt_stop = (Button) mainActivity.findViewById(R.id.button2);
}
@Test
public void serviceIsOn(){
bt_start.performClick();
Intent intent = Robolectric.shadowOf(mainActivity).peekNextStartedService();
assertEquals(MiService.class.getCanonicalName(),intent.getComponent().getClassName());
}
然后我运行测试,一切正常Robolectric有一个类似活动的服务生命周期。此控制器提供执行相应服务回调的所有方法(例如,controller.attach().create().startCommand(0,0).destroy()
)
理论上,我们可以预期,它将通过其内部处理程序触发IntentService.onHandleIntent(Intent)
。然而,这个处理程序
使用了一个在后台线程上运行的活套
,我不知道如何使这个线程前进到下一个任务。解决方法是创建模拟相同行为的TestService
,但在主线程(用于运行测试的线程)上触发onHandleIntent(Intent)
@RunWith(RobolectricGradleTestRunner.class)
公共类MyIntentService测试{
私人测试服务;
专用服务控制器;
@以前
公共作废设置(){
controller=roblectric.buildService(TestService.class);
service=controller.attach().create().get();
}
@试验
public void testWithIntent(){
Intent Intent=新的Intent(RuntimeEnvironment.application、TestService.class);
//向意图中添加额外内容
控制器.withIntent(intent).startCommand(0,0);
//在此断言
}
@之后
公共无效拆卸(){
controller.destroy();
}
公共静态类TestService扩展了MyIntentService{
启用公共布尔值=true;
@凌驾
公共无效启动(Intent Intent,int startId){
//与内部ServiceHandler.handleMessage()中的逻辑相同
//但运行在与服务相同的线程上
onHandleIntent(意图);
stopSelf(startId);
}
}
}
更新:或者,为IntentService创建类似的控制器非常简单,如下所示:
public class IntentServiceController<T extends IntentService> extends ServiceController<T> {
public static <T extends IntentService> IntentServiceController<T> buildIntentService(Class<T> serviceClass) {
try {
return new IntentServiceController<>(Robolectric.getShadowsAdapter(), serviceClass);
} catch (IllegalAccessException | InstantiationException e) {
throw new RuntimeException(e);
}
}
private IntentServiceController(ShadowsAdapter shadowsAdapter, Class<T> serviceClass) throws IllegalAccessException, InstantiationException {
super(shadowsAdapter, serviceClass);
}
@Override
public IntentServiceController<T> withIntent(Intent intent) {
super.withIntent(intent);
return this;
}
@Override
public IntentServiceController<T> attach() {
super.attach();
return this;
}
@Override
public IntentServiceController<T> bind() {
super.bind();
return this;
}
@Override
public IntentServiceController<T> create() {
super.create();
return this;
}
@Override
public IntentServiceController<T> destroy() {
super.destroy();
return this;
}
@Override
public IntentServiceController<T> rebind() {
super.rebind();
return this;
}
@Override
public IntentServiceController<T> startCommand(int flags, int startId) {
super.startCommand(flags, startId);
return this;
}
@Override
public IntentServiceController<T> unbind() {
super.unbind();
return this;
}
public IntentServiceController<T> handleIntent() {
invokeWhilePaused("onHandleIntent", getIntent());
return this;
}
}
公共类IntentServiceController扩展ServiceController{
公共静态IntentService控制器buildIntentService(类serviceClass){
试一试{
返回新的IntentServiceController(Robolectric.getShadowsAdapter(),serviceClass);
}catch(IllegalAccessException |实例化exception e){
抛出新的运行时异常(e);
}
}
私有IntentServiceController(ShadowsAdapter ShadowsAdapter,类serviceClass)抛出IllegaAccessException、InstanceionException{
超级(暗影攻击机,服务级);
}
@凌驾
具有意图的公共意图服务控制器(意图){
超级。故意(故意);
归还这个;
}
@凌驾
公共意图服务控制器连接(){
super.attach();
归还这个;
}
@凌驾
public-IntentServiceController绑定(){
super.bind();
归还这个;
}
@凌驾
公共IntentServiceController创建(){
super.create();
归还这个;
}
@凌驾
公共意图服务控制器销毁(){
super.destroy();
归还这个;
}
@凌驾
公共意图服务控制器重新绑定(){
super.rebind();
归还这个;
}
@凌驾
公共IntentServiceController startCommand(int标志,int STARTTID){
super.startCommand(旗帜,startId);
归还这个;
}
@凌驾
公共意图服务控制器解除绑定(){
super.unbind();
归还这个;
}
公共意图服务控制员手册内容(){
调用whilepaused(“onHandleIntent”,getIntent());
归还这个;
}
}
Robolectric 3.1+
创建服务的实例
直接呼叫HandleContent
YourService svc = Robolectric.buildService(YourService.class).get();
Intent fakeIntent = new Intent();
fakeIntent.putExtra(YourService.SOME_EXTRA, "debug|fail");
svc.onHandleIntent(fakeIntent);
assertThat(something.happened).isEqualTo(true);
注意:即使您正在测试IntentService,也要使用Robolectric.buildService
(而不是.buildIntentService
)<据我所知,code>.buildIntentService
目前不工作
更新2017-05-17:
buildIntentService
的问题将是您没有按照OP的要求测试服务的onhandlecontent
。您正在测试活动是否调用service.Hi。我遵循了你的指导方针。我不需要在我的测试用例中编写服务,只需要包含一个调用OnHandleContent的公共方法,它也通过了我的意图。。而是让我的活动启动服务。。我只是实例化这个服务
YourService svc = Robolectric.buildService(YourService.class).get();
Intent fakeIntent = new Intent();
fakeIntent.putExtra(YourService.SOME_EXTRA, "debug|fail");
svc.onHandleIntent(fakeIntent);
assertThat(something.happened).isEqualTo(true);