2012-08-12 3 views
6

Я новичок в тестировании на Android, я хочу протестировать IntentService, и в настоящее время я расширяю ServiceTestCase.как проверить JUnit IntentService

Я пытаюсь использовать ResultReceiver, но проблема в том, что OnReceiveResult никогда не вызывается в тестовом корпусе. (Я также попытался создания ResultReceiver с new Handler() в качестве аргумента insetad из null, но с тем же результатом.

, что я делаю неправильно? , что это правильный способ испытать IntentService?

это услуга :

public class MyService extends IntentService { 

public MyService() { 
    super("MyService"); 
} 

public MyService(String name) { 
    super(name); 
} 

@Override 
protected void onHandleIntent(Intent intent) { 
    final int action = intent.getIntExtra("action", 0); 
    final int request = intent.getIntExtra("request", 0); 
    final ResultReceiver receiver = (ResultReceiver) intent.getExtras().get("receiver"); 

    if (receiver == null) { 
     return; 
    } 

    if (action == 0 || request == 0) { 
     receiver.send(0, null); 

     return; 
    } 
} 

}

и это испытание:

public void testHandleInvalidRequests() { 
    ResultReceiver receiver = new ResultReceiver(null) { 
     @Override 
     protected void onReceiveResult(int resultCode, Bundle resultData) { 
      fail(); 
     } 
    }; 

    Intent intent = new Intent(mContext, MyService.class); 
    intent.putExtra("receiver", receiver); 
    startService(intent); 

} 

ответ

4

Мне удалось проверить мой IntentService, и я покажу вам концептуально, как я это сделал.

Во-первых, вы расширяете класс тестирования приложений для Android: ServiceTestCase<MyIntentService>. Затем вы в основном запускаете IntentService, как вы это делали, используя startService(intent).

Поскольку сервис под тестированием является IntentService, он будет работать в порожнем рабочем потоке. Если вы не заблокируете тестовый поток, тогда ваш тестовый метод немедленно сделает утверждения, которые, очевидно, потерпят неудачу, поскольку тестовая работа в фоновом режиме, вероятно, еще не завершена. В конце концов, метод тестирования вернется, и ваш тест завершится неудачно.

Что вам нужно сделать, это заблокировать тестовый поток после startService. Сделайте это, используя ReentrantLock и Условие, вызывающее await() на нем.

IntentService затем выполняет onHandleIntent в фоновом режиме. Я предлагаю вам расширить свой IntentService и переопределить onHandleIntent, вызвав super.onHandleIntent(), и после этого сообщите тестовой теме, что работа выполнена. Сделайте это с той же блокировкой и условием, используемым для блокировки тестовой нити.

+1

Можете ли вы привести пример использования ReentrantLock здесь? –

+0

Мне тоже очень понравился бы пример (даже два года спустя). Спасибо. – JDenais

+0

Привет, любой контекст, который я использовал для инициализации намерения, похоже, выбрасывает исключение нулевого указателя. Как вы создали свой контекст? – kyrax

0

Если startService() в тестовый файл проходит ServiceTestCase<>, я нашел в Android Studio 1.1 в тестовом объекте, который ServiceTestCase не экземпляр IntentService объекта через onHandleIntent().
См. Android ServiceTestCase for IntentService для получения дополнительной информации.

0

Я знаю, что это старо, но поскольку у меня была такая же проблема, я отправлю здесь, как мне, наконец, удалось запустить тест на IntentService. Как сказал @Joerg, это проблема с резьбой.

public class MyServiceTest extends ServiceTestCase<MyService> { 
    public MyServiceTest() { 
     super(MyService.class); 
    } 

    public void testOnHandleIntent() throws Exception { 
     Looper.prepare(); 
     final CountDownLatch latch = new CountDownLatch(1); 

     ResultReceiver receiver = new ResultReceiver(new Handler()) { 
      @Override 
      protected void onReceiveResult(int resultCode, Bundle resultData) { 
       latch.countDown(); 

       assertEquals(resultCode, 0); 
       assertNull(resultData); 
       fail(); 

       Looper.myLooper().quit(); 
      } 
     }; 

     Intent intent = new Intent(getSystemContext(), MyService.class); 
     intent.putExtra("receiver", receiver); 
     getSystemContext().startService(intent); 

     Looper.loop(); 

     assertThat(latch.getCount(), is(0L)); 
    } 
} 

В Looper и Handler классов необходимы, так что обратный вызов имеет резьбу, чтобы быть вызван. Защелка существует только в качестве примера блокировки и как средство для подтверждения того, что код, переданный обратным вызовом до конца метода тестирования.

Если метод quit()Looper не вызывается, тест висит.

ServiceTestCase осуждается на последних версиях Android, но замена (ServiceTestRule) не поддерживает IntentService ...

Смежные вопросы