19

usingのonHandleIntent()メソッドをテストしようとしています。IntentServiceRobolectric

私は次のサービスを開始しています:

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);

startedIntentnullではないようonHandleIntent()ですが、呼び出されていないようです。

どのようにテストすればよいですか?

4

5 に答える 5

14

Robolectric には、ServiceControllerアクティビティと同じようにサービス ライフサイクルを通過できる があります。このコントローラーは、対応するサービス コールバックを実行するためのすべてのメソッドを提供します (例: controller.attach().create().startCommand(0, 0).destroy())。

理論的には、その内部を介してIntentService.onStartCommand()がトリガーさ れると予想できます。ただし、これはバックグラウンド スレッドで実行される を使用しており、このスレッドを次のタスクに進める方法がわかりません。回避策は、同じ動作を模倣するものを作成することですが、メイン スレッド (テストの実行に使用されるスレッド) でトリガーされます。IntentService.onHandleIntent(Intent)HandlerHandlerLooperTestServiceonHandleIntent(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;
    }
}
于 2015-11-17T11:13:52.207 に答える
6

onHandleIntentは保護されたメソッドであるため、直接呼び出すことはできません。

私の解決策は、テストケースでサービスクラスを拡張し、オーバーライドonHandleIntentして公開して呼び出すことでしたsuper.onHandleIntent(intent)

onHandleIntent次に、テスト ケースから直接呼び出します。

于 2012-09-29T15:44:20.817 に答える
1

あなたはこれに間違った方法でアプローチしたと思います。ここでテストしています:

Intent startedIntent = shadowActivity.getNextStartedService();
assertNotNull(startedIntent);

startService()呼ばれていました。

startService()次に、Android がエンドを正しく実装し、サービスの呼び出し後に実際に開始されると想定する必要があります。

の動作をテストしたい場合はonHandleIntent()、直接呼び出す必要があると思いますか??

正確にはわかりません...しかし、あなたが書きたいテストは、Androidフレームワークをテストするだけだと思います。2 つのテストを作成する必要があります。

1)呼び出されるテストstartService()(例のように)。

onHandleIntent()2) (直接呼び出して)の動作をテストします。

経験はほとんどありませんがRobolectric、これが役立つことを願っています。

乾杯

于 2012-09-29T11:25:41.200 に答える
1

私はこれを使います

@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());
}

そして、テストを実行すると、すべて問題ありません

于 2014-02-10T20:39:41.823 に答える