Robolectric 有一个ServiceController
可以像活动一样贯穿服务生命周期的服务。该控制器提供所有方法来执行相应的服务回调(例如controller.attach().create().startCommand(0, 0).destroy()
)。
理论上我们可以预期IntentService.onStartCommand()
会触发 IntentService.onHandleIntent(Intent)
,通过它的内部Handler
。但是,这Handler
使用Looper
在后台线程上运行的 a,我不知道如何使该线程前进到下一个任务。一种解决方法是创建TestService
模仿相同行为但onHandleIntent(Intent)
在主线程(用于运行测试的线程)上触发。
@RunWith(RobolectricGradleTestRunner.class)
public class MyIntentServiceTest {
private TestService service;
private ServiceController<TestService> controller;
@Before
public void setUp() {
controller = Robolectric.buildService(TestService.class);
service = controller.attach().create().get();
}
@Test
public void testWithIntent() {
Intent intent = new Intent(RuntimeEnvironment.application, TestService.class);
// add extras to intent
controller.withIntent(intent).startCommand(0, 0);
// assert here
}
@After
public void tearDown() {
controller.destroy();
}
public static class TestService extends MyIntentService {
public boolean enabled = true;
@Override
public void onStart(Intent intent, int startId) {
// same logic as in internal ServiceHandler.handleMessage()
// but runs on same thread as Service
onHandleIntent(intent);
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;
}
}