Robolectric и IntentServices

Используя Robolectric, как можно протестировать IntentService, который передает намерения в качестве ответа?

Предполагая следующий класс:

class MyService extends IntentService {
    @Override
    protected void onHandleIntent(Intent intent) {
        LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent("action"));
    }
}

В моем тестовом примере я пытаюсь сделать что-то вроде этого:

@RunWith(RobolectricTestRunner.class)
public class MyServiceTest{
    @Test
    public void testPurchaseHappyPath() throws Exception {

        Context context = new Activity();

        // register broadcast receiver
        BroadcastReceiver br = new BroadcastReceiver() {

            @Override
            public void onReceive(Context context, Intent intent) {
                // test logic to ensure that this is called
            }

        };
        context.registerReceiver(br, new IntentFilter("action"));

        // This doesn't work
        context.startService(new Intent(context, MyService.class));

    }

}

MyService никогда не запускается с использованием этого подхода. Я относительно новичок в Robolectric, поэтому, вероятно, упускаю что-то очевидное. Есть ли какая-то привязка, которую я должен сделать перед вызовом startService? Я проверил, что вещание работает, просто вызвав sendBroadcast в контексте. Есть идеи?


person pbaumann    schedule 26.07.2012    source источник
comment
У меня нет конкретного решения для вас, но я думаю, что вам нужно издеваться над широковещательным приемником с помощью mockito, чтобы иметь возможность вызывать onReceive внутри вашего кода. Или проще было бы извлечь логику из onReceive в отдельный тестовый пример.   -  person andreasg    schedule 27.07.2012
comment
Вещательный приемник на самом деле работает просто отлично. Как я сказал в нижней части поста выше, вызов context.sendBroadcast попадает в onReceive. Это инициализация службы, которую я не вижу.   -  person pbaumann    schedule 27.07.2012
comment
Вы нашли решение? Я столкнулся с той же проблемой, пытаясь проверить IntentService   -  person Gal Ben-Haim    schedule 19.08.2012


Ответы (1)


Вы не можете протестировать инициализацию службы, как вы пытаетесь это сделать. Когда вы создаете новое действие в Robolectric, возвращаемое вами действие на самом деле представляет собой ShadowActivity (вроде). Это означает, что когда вы вызываете startService, фактически выполняется метод этот, который просто вызывает ShadowApplication#startService. Это содержимое этого метода:

@Implementation
@Override
public ComponentName startService(Intent intent) {
    startedServices.add(intent);
    return new ComponentName("some.service.package", "SomeServiceName-FIXME");
}

Вы заметите, что на самом деле он вообще не пытается запустить вашу службу. Он просто отмечает, что вы попытались запустить службу. Это полезно в том случае, если какой-то тестируемый код должен запускать службу.

Если вы хотите протестировать реальную службу, я думаю, вам нужно смоделировать жизненный цикл службы для бита инициализации. Что-то вроде этого может сработать:

@RunWith(RobolectricTestRunner.class)
public class MyServiceTest{
    @Test
    public void testPurchaseHappyPath() throws Exception {

        Intent startIntent = new Intent(Robolectric.application, MyService.class);
        MyService service = new MyService();
        service.onCreate();
        service.onStartCommand(startIntent, 0, 42);

        // TODO: test test test

        service.onDestroy();
    }
}

Я не знаком с тем, как Robolectric обращается с BroadcastReceivers, поэтому я пропустил это.

РЕДАКТИРОВАТЬ. Возможно, имеет смысл выполнять создание/удаление службы в методах JUnit @Before/@After, что позволит вашему тесту содержать только биты onStartCommand и "test test test".

person Edward Dale    schedule 17.10.2012