Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/178.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是否可以在测试用例中注册接收器?_Java_Android_Testing_Broadcastreceiver_Alarmmanager - Fatal编程技术网

Java 是否可以在测试用例中注册接收器?

Java 是否可以在测试用例中注册接收器?,java,android,testing,broadcastreceiver,alarmmanager,Java,Android,Testing,Broadcastreceiver,Alarmmanager,我想在单元内部测试是否触发了使用AlarmManager编程的报警,如果是,是否在正确的时间段内触发 这是要测试的接收器类。 我已经在我的测试项目中创建了它。 (注意:未在舱单中登记) 这是单元测试。programReceiver方法实际上属于主项目中的一个类,但我已将其包含在测试中,因此您不需要阅读太多代码 public class ATest extends AndroidTestCase { MockBroadcastReceiver mockReceiver; @Ov

我想在单元内部测试是否触发了使用
AlarmManager
编程的报警,如果是,是否在正确的时间段内触发

这是要测试的接收器类。 我已经在我的测试项目中创建了它。 (注意:未在舱单中登记)

这是单元测试。
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
        );
    }   
}
公共类ATest扩展了AndroidTestCase{
模拟接收机模拟接收机;
@凌驾
受保护的void setUp()引发异常{
mockReceiver=新的MockBroadcastReceiver();
getContext().registerReceiver(mockReceiver,new IntentFilter());
}
@凌驾
受保护的void tearDown(){
getContext().unregisterReceiver(mockReceiver);
mockReceiver=null;
}
公开无效测试(){
//我们将进行两次编程,并检查是否只有最后一次
//编程报警应保持激活状态。
最终对象标志=新对象();
MockBroadcastReceiver.setNumTimeScaled(0);
新线程(){
@凌驾
公开募捐{
programReceiver(getContext(),MockBroadcastReceiver.class,60000,60000);
系统时钟。睡眠(20000);
programReceiver(getContext(),MockBroadcastReceiver.class,60000,60000);
系统时钟。睡眠(90000);
已同步(标志){
flag.notifyAll();
}
}
}.start();
已同步(标志){
试一试{
flag.wait();
}捕捉(中断异常e){
}
}
assertEquals(1,MockBroadcastReceiver.getNumTimesCalled());//应至少调用一次,但其值为0。
}

private static void programReceiver(上下文,类我不确定为什么您的测试不能按预期工作。我想到了几个建议:

  • 我所看到的大多数文档,例如[1],都建议在循环中根据不成立的条件调用
    Object.wait()
    。您的代码不会这样做。也许您可以尝试重新处理它,使其成立
  • 为了完整起见,也许您应该为
    InterruptedException
    输出一些可以由
    flag.wait()抛出的内容,以防万一

  • [1]

    在android源代码中,有一个使用broadcastreceiver执行alarmManager.setInexactRepeating的

    主要区别在于,android测试的工作延迟为15分钟,而您的测试使用1分钟的延迟

    Android的文档说明:

    。。。 intervalMillis警报后续重复之间的间隔(毫秒)。在API 19之前,如果这是间隔十五分钟、间隔半小时、间隔小时、间隔半天或间隔天中的一个,则警报将与其他警报进行相位对齐,以减少唤醒次数。否则,警报将被设置为应用程序调用了setRepeating(int、long、long、pendingEvent)。从API 19开始,所有重复报警都将是不精确的,并且会与其他报警进行批处理,而不管它们所述的重复间隔如何

    我不是舒尔,如果这意味着只允许15分钟的多音


    在我的Android 2.2手机上,不精确计时器只有在15分钟的倍数下才能工作。

    因此答案是肯定的,这是可能的,但接收器只能在隐式(基于动作的)意图和意图过滤器下工作

    显式意图(基于类,没有筛选器)不适用于动态注册的接收者。要使显式意图起作用,您需要在清单中注册接收者,而不是像我尝试的那样动态注册接收者

    这是安卓系统中最黑暗、记录最少的功能之一。根据我对intents的经验,你永远无法确定。而且这也很难诊断,因为logcat中没有任何可以帮助理解问题的警告。这里为@d2vid的回答致敬:

    因此,要修复代码,我必须在清单中的应用程序标记内添加receiver元素。由于receiver是在测试项目内创建的模拟receiver类,我必须编辑测试项目清单,而不是主项目清单。但另一方面,在Eclipse测试项目中,添加到清单的receiver标记似乎不起作用.Android Studio看起来更适合清单合并,但这是一个在Eclipse中启动的遗留项目,我们不会移植它


    总而言之:在Eclipse中,对于主项目中不存在的接收器,显式意图测试被破坏。我需要测试的类只使用显式意图,因此我的测试不能在Eclipse中编写。

    AlarmManager不是问题所在。在较低级别上有某种东西阻止调用接收器。请阅读我的更新。轻视答案不是正确的,赏金是当之无愧的,因为您链接的测试向我表明,与我的代码的唯一区别是使用了隐式意图和意图过滤器。虽然我同意同步代码可能更好,但它在99,99%的情况下都能工作,对于脏单元测试也没问题。
    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
            );
        }   
    }
    
     public void setInexactRepeating (int type, long triggerAtMillis, long intervalMillis, PendingIntent operation)