我想在单元测试中测试使用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),但模拟接收器中的计数器为0.我已经在onReceive
方法中设置了一个断点,并且它从未命中。我还添加了日志记录,并没有在logcat中显示。所以我100%确定接收器没有被调用。我也尝试增加线程中的睡眠时间,因为setInexactRepeating
非常不精确,但我可以等待很长时间,但它仍然没有被调用。
我也尝试注册它在测试项目的清单,而不是编程方式,结果是相同的。
为什么接收机不被呼叫?
UPDATE
我可以确认AlarmManager
不是问题。根据adb dumpsys警报正确注册警报。
我现在试图通过调用sendBroadcast
来让接收器运行,但我处于死路一条。接收器不会被叫。我尝试了主要的应用上下文,测试用例上下文,甚至是ActivityInstrumentationTestCase2
。试过还添加了WakeLocks而没有任何东西。没有办法让它被调用。我认为这可能是由意图或意图过滤器中的一些标志引起的(android似乎对标志非常挑剔)。
虽然我同意同步代码可能会更好,但它可以在99.99%的情况下工作,对于脏单元测试也可以。 –