Robolectric には、ServiceController
アクティビティと同じようにサービス ライフサイクルを通過できる があります。このコントローラーは、対応するサービス コールバックを実行するためのすべてのメソッドを提供します (例: controller.attach().create().startCommand(0, 0).destroy()
)。
理論的には、その内部を介してIntentService.onStartCommand()
がトリガーさ れると予想できます。ただし、これはバックグラウンド スレッドで実行される を使用しており、このスレッドを次のタスクに進める方法がわかりません。回避策は、同じ動作を模倣するものを作成することですが、メイン スレッド (テストの実行に使用されるスレッド) でトリガーされます。IntentService.onHandleIntent(Intent)
Handler
Handler
Looper
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);
}
}
}
UPDATE : または、次のように、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;
}
}