'Testing Intent that will be triggered by an alarm

I'm trying to set unit test for my android app. I have to test a notifications services that looks like that :

This class provide function to set notification in a context

class DeadlineNotification {
    companion object {
        private lateinit var alarmManager: AlarmManager
        private lateinit var pendingIntent: PendingIntent
        /*
        Create a notification channel for reminder notifications
        Creating an existing notification channel with its original values performs no operation,
        so it's safe to call this code when starting an app.
        */
        fun createNotificationChannel(context: Context){
            val channelName :CharSequence = "reminders channel"
            val description = "channel for reminders notifications"
            val channel = NotificationChannel("remindersChannel", channelName, NotificationManager.IMPORTANCE_DEFAULT)
            val notificationManager = context.getSystemService(NotificationManager::class.java)

            channel.description=description

            notificationManager.createNotificationChannel(channel)
        }

        /*
        Set a notification that will be triggered in a given time in ms.
        you can pass a title/description and Id in parameter
        */
        fun setNotification(timeMS: Long, title: String, description: String, id: Int, context: Context){
            alarmManager = context.getSystemService(AppCompatActivity.ALARM_SERVICE) as AlarmManager  //this get an service instance of AlarmManager
            val intent = Intent(context, ReminderBroadcastReceiver::class.java) //this create an intent of broadcast receiver
            //Adding extra parameter that will be used in the broadcase receiver to create the notification
            intent.putExtra("title", title)
            intent.putExtra("description", description)
            intent.putExtra("id", id)

            //set the receiver as pending intent
            pendingIntent = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_IMMUTABLE)

            //set an alarm that will wake up the pending intent (receiver)
            alarmManager.setExact(AlarmManager.RTC_WAKEUP, timeMS, pendingIntent)

        }

        fun getAlarmManager():AlarmManager = this.alarmManager
    }
}

setNotification will set an Alarm that will launch an intent of ReminderBroadcastReceiver :

//this class is a BroadcastReceiver that will send a notification when it is triggered
class ReminderBroadcastReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context?, intent: Intent?) {
        var channelId = "remindersChannel"

        //retrieving some parameters for the notification
        var title = intent!!.getStringExtra("title")
        var content = intent!!.getStringExtra("description")
        var notifId = intent!!.getIntExtra("id", 0)

        val intent2 = Intent(context, MainActivity::class.java)
        intent2!!.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK

        //this is the intent where the user will be send when clicking on the notification
        val pendingIntent = PendingIntent.getActivity(context, 0, intent2, PendingIntent.FLAG_IMMUTABLE)

        //Builder of the notification
        val notifBuilder = NotificationCompat.Builder(context!!, channelId)
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setContentTitle(title + notifId.toString())
            .setContentText(content)
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)
            .setCategory(NotificationCompat.CATEGORY_REMINDER)
            .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)

        //send the notification
        val notificationManager = NotificationManagerCompat.from(context)
        notificationManager.notify(notifId, notifBuilder.build())
    }
}

This will create a NotificationManager and send the notification.

The code above is working as expected.

Now I'm trying to write unit test for it, I tried this :

@RunWith(AndroidJUnit4::class)
class DeadlineNotificationTest {


    @Test
    fun `notification is triggered at currentTime and redirect to MainActivity`() {


        val activity: MainActivity = Robolectric.setupActivity(MainActivity::class.java) //main Activity
        DeadlineNotification.setNotification(System.currentTimeMillis(), "title", "empty description", 1, activity) //this create an alarm
        //here we're looking for the notificationManager that have been
        val notificationService: NotificationManager = activity.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        val shadowNotificationManager =
            shadowOf(notificationService)

        assertEquals(1, shadowNotificationManager.size())

        val notification: Notification = shadowNotificationManager.allNotifications[0]

        val contentIntent: PendingIntent = notification.contentIntent

        val nextIntent = shadowOf(contentIntent).savedIntent

        val nextClassName = nextIntent.component!!.className
        assertEquals(nextClassName, MainActivity::class.java.getName())

    }
}

But the first assertion fails, so I assume the shadowNotificationManager cannot see the notification. Do you have any Idea how I should proceed to have a working test?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source