Я хочу протестировать внутри единичного теста, был ли запущен сигнал тревоги, запрограммированный с помощью AlarmManager
, и если да, то если он срабатывает в течение правильного периода.Возможно ли зарегистрировать приемник в тестовом примере?
Вот класс приемника для тестирования. Я создал его в своем тестовом проекте. (Примечание: это не зарегистрирован в манифесте)
public class MockBroadcastReceiver extends BroadcastReceiver {
private static int numTimesCalled = 0;
MockBroadcastReceiver(){
numTimesCalled = 0;
}
@Override
public void onReceive(Context context, Intent intent) {
numTimesCalled++;
}
public static int getNumTimesCalled() {
return numTimesCalled;
}
public static void setNumTimesCalled(int numTimesCalled) {
MockBroadcastReceiver.numTimesCalled = numTimesCalled;
}
}
А вот тест на блок. Метод programReceiver
фактически принадлежит классу основного проекта, но я включил его внутри теста, так что вам не нужно читать столько кода.
public class ATest extends AndroidTestCase {
MockBroadcastReceiver mockReceiver;
@Override
protected void setUp() throws Exception {
mockReceiver = new MockBroadcastReceiver();
getContext().registerReceiver(mockReceiver, new IntentFilter());
}
@Override
protected void tearDown() {
getContext().unregisterReceiver(mockReceiver);
mockReceiver = null;
}
public void test(){
//We're going to program twice and check that only the last
//programmed alarm should remain active.
final Object flag = new Object();
MockBroadcastReceiver.setNumTimesCalled(0);
new Thread(){
@Override
public void run(){
programReceiver(getContext(), MockBroadcastReceiver.class, 60000, 60000);
SystemClock.sleep(20000);
programReceiver(getContext(), MockBroadcastReceiver.class, 60000, 60000);
SystemClock.sleep(90000);
synchronized(flag){
flag.notifyAll();
}
}
}.start();
synchronized(flag){
try {
flag.wait();
} catch (InterruptedException e) {
}
}
assertEquals(1, MockBroadcastReceiver.getNumTimesCalled()); //should have been called at least once, but its 0.
}
private static void programReceiver(Context context, Class<? extends BroadcastReceiver> receiverClass, long initialDelay, long period){
Intent intent = new Intent(context, receiverClass);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent); //Cancel any previous alarm
alarmManager.setInexactRepeating (
AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + initialDelay,
period,
pendingIntent
);
}
}
Когда я выполнить метод test
, приемник должен быть зарегистрирован динамически в setUp
. Затем я программирую один и тот же сигнал тревоги дважды. Мое намерение состояло в том, чтобы проверить, что только последний сигнал остался активным, но мне не удается вообще вызвать приемник. Тест завершается неудачно, поскольку ожидается, что он будет вызываться один раз (или, по крайней мере, несколько раз> = 1), но счетчик в mock-приемнике равен 0. Я установил точку останова в методе onReceive
, и он никогда не попадает , Я также добавил регистрацию и ничего не отображается в logcat. Поэтому я на 100% уверен, что приемник не вызван. Я также попытался увеличить время сна в потоке, потому что setInexactRepeating
срабатывает очень неточно, но я могу ждать веков, и он все еще не называется.
Я также попытался зарегистрировать его в манифесте тестового проекта, а не программно, и результаты остались прежними.
Почему приемник не называется?
UPDATE
Я могу подтвердить AlarmManager
не проблема. Аварийные сигналы правильно регистрируются в соответствии с аварийным сигналом adb dumpsys.
Теперь я пытаюсь запустить приемник, позвонив по телефону sendBroadcast
, но я в тупике. Приемник просто не будет вызван. Я пробовал основной контекст приложения, контекст тестового случая, даже ActivityInstrumentationTestCase2
. Пробовал также добавлять WakeLocks и ничего. Просто нет способа заставить его позвонить. Я думаю, что это может быть вызвано некоторыми флагами в фильтре намерения или намерения (андроид, похоже, очень разборчив с флагами).
Хотя я согласен, что код синхронизации может быть лучше, он будет работать в 99,99% случаев, и это нормально для грязного модульного теста. –