Android ServiceTestCase для IntentService

В настоящее время я пишу юнит-тесты для приложений Android и наткнулся на следующую проблему:

Я использую ServiceTestCase проверить IntentService как это:

@Override
public void setUp() throws Exception {
    super.setUp();      
}

public void testService()
{
    Intent intent = new Intent(getSystemContext(), MyIntentService.class);
    super.startService(intent);     
    assertNotNull(getService());        
}

Однако я заметил, что мой IntentService создается (означает, что onCreate называется) но я никогда не получаю звонок в onHandleIntent(Intent intent)

Кто-нибудь уже проверял IntentService с ServiceTestCase учебный класс?

Спасибо!

5 ответов

Решение

Я только начал тестировать свой собственный IntentService и это оказывается немного головной болью.

Все еще пытаюсь разобраться, но для сценария, где кажется, что вы не получаете вызов вашего метода onHandleIntent(), (Я не очень хорошо разбираюсь в технических деталях junit так что простите за использование терминологии) это должно быть потому, что тестовая структура, основанная на вашем коде, фактически разрушает или завершает тестовый метод после вашего вызова startService возвращается. Недостаточно времени для onHandleIntent быть вызванным.

Я проверил вышеупомянутую теорию, добавив бесконечный цикл в моем тестовом примере - только тогда я смогу увидеть свои операторы журнала в onHandleIntent журнал.

Это немного поздно, но я просто боролся с этим. Вы можете решить эту проблему, создав класс, который просто переопределяет onStart вашей службы, поэтому он вызывает onHandleIntent непосредственно. Так, например, если у вас есть LocationUpdaterService, вы можете создать поддельный класс, который переопределяет onStart функционировать так:

public class LocationUpdaterServiceFake extends LocationUpdaterService {

@Override
public void onStart(Intent intent, int startId) {
    onHandleIntent(intent);
    stopSelf(startId);
}

LocationUpdaterService является подклассом IntentService, поэтому, когда вы пишете свои тесты, просто используйте LocationUpdaterServiceFake класс как это

public class LocationUpdateServiceTest extends ServiceTestCase<LocationUpdaterServiceFake> {

public LocationUpdateServiceTest()
{
    super(LocationUpdaterServiceFake.class);
}

public void testNewAreaNullLocation()
{
    Intent intent = new Intent();
    intent.setAction(LocationUpdaterService.ACTION_NEW_AREA);

    startService(intent);
}

}

Теперь всякий раз, когда вы звоните startService, он пропустит код потоков в IntentService и просто вызовет onHandleIntent функция

Вам просто нужно добавить:

Thread.sleep(XXXXXXX); 

Выбрать XXXX после startService, он позволит потоку перейти в onHandleIntent метод.

В Android Studio 1.1 при запуске тестов с использованием конфигурации Run/Debug | Средство тестирования Android на любом тестируемом модуле (UUT), который расширяет IntentService, код ServiceTestCase.java (JUnit?) Не вызывает метод onHandleIntent(намерение) в проверяемом оборудовании. ServiceTestCase вызывает только onCreate, поэтому проблема в тестовом коде.

protected void startService(Intent intent) {
    if (!mServiceAttached) {
        setupService();
    }
    assertNotNull(mService);

    if (!mServiceCreated) {
        mService.onCreate();
        mServiceCreated = true;
    }
    mService.onStartCommand(intent, 0, mServiceId);

    mServiceStarted = true;
}

В моем файле smSimulatorTest.java:

public class smSimulatorTest extends ServiceTestCase<smSimulator> 

На данный момент, я ищу другие решения в среде тестирования, которые проверяют UUT через Intents, поскольку именно так создается IntentService.

http://developer.android.com/reference/android/app/IntentService.html - чтобы использовать его, расширьте IntentService и внедрите onHandleIntent(Intent). IntentService получит Intents, запустит рабочий поток и остановит службу соответствующим образом.

Я, как и другие, помещаю свой код в onHandleintent(), как указано в приведенной выше документации, однако ServiceTestCase тестирует только onStart, а onStartCommand было показано выше.

Это мой подход на данный момент:

  1. Начальный Intent, который вызывает службу, указывает метод Service для тестирования

    
    public void test_can_do_the_work() {
        Intent startIntent = new Intent();
        startIntent.putExtra("IN_TEST_MODE", "TEST_SPECIFIC_METHOD");
        startIntent.setClass(getContext(), MyServiceToTest.class);
        startService(startIntent);
        assertNotNull(getService()); // Your assertion Service specific assertion
    }
    
  2. В сервисе onStart мы проверяем наличие определенного переданного Extra и вызываем метод для тестирования. Это не будет выполнено, когда Handle намерение сработало.

    
    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        String in_test_mode = intent.getStringExtra("TEST_SPECIFIC_METHOD");
        if(in_test_mode != null){
            doServiceWork();
        }
    }
    
Другие вопросы по тегам