Java – can I register a receiver in a test case?

I want to test whether the alarm programmed with AlarmManager is triggered in the unit test. If so, it will be triggered within the correct time

The following are the receiver classes to test I created it in my test project (Note: it is not registered in the list)

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;
    }
}

This is a unit test The programreceiver method actually belongs to a class in the main project, but I have included it in the test, so you don't need to read so much code

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(),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,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
        );
    }   
}

When I execute the test method, the receiver should have been dynamically registered in setup Then I programmed the same alarm clock twice My intention is to test that only the last alarm is still active, but I can't make the receiver called The test failed because it is expected to be called once (or at least more > = 1), but the counter in the analog receiver is 0 I have set a breakpoint in the onReceive method that will never hit I also added log records, which are not displayed in logcat So I'm 100% sure the receiver wasn't called I also try to increase the sleep time in the thread, because setinexactrepeating is triggered very incorrectly, but I can wait for age, but it is still not called

I also tried to register it in the test project list instead of programmatically, and the result was the same

Why is the recipient not called?

Update I can confirm that the AlarmManager is not a problem Alarms are registered correctly according to ADB dumpsys alarms

I'm trying to get the receiver to run by calling sendbroadcast, but I'm at a dead end The receiver will not be called I tried the main application context, the test case context, and even the activity instrumentation test case 2 Have you tried and added wakelocks and no There is no way to get it I think this may be caused by intention or some flags in the intention filter (Android seems to be really picky about flags)

Solution

There is an AlarmManager test in the Android source code, which uses the broadcast receiver to execute the AlarmManager setInexactRepeating.

The main difference is that the working Android test is delayed by 15 minutes, while your test uses a one minute delay

AlarmManager's Android document says:

public void setInexactRepeating (int type,long triggerAtMillis,long intervalMillis,PendingIntent operation)

... interval in milliseconds Before API 19, if this is interval_ FIFTEEN_ One of the minutes, interval_ HALF_ HOUR,INTERVAL_ HOUR,INTERVAL_ HALF_ Day or interval_ Day, the alarm will be aligned with other alarms to reduce the number of wakeups Otherwise, the alarm will be set to the application calling setrepeating (int, long, pendingintent) Starting from API 19, all duplicate alarms will be inaccurate and batch processed with other alarms regardless of the repetition interval

If this means that only 15 minutes of polygons are allowed, I'm not comfortable

On my Android 2.2 phone, the imprecise timer only works in 15 minutes

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>