Photo by Joseph James : Christmas Market: A Sneak Peek ✨

Testing Firebase Cloud Messaging with Espresso

Joseph James (JJ)
2 min readAug 13, 2023

--

Push notifications play a pivotal role in enhancing user engagement with mobile applications. Ensuring the consistent behavior of these notifications, especially in Android apps, is essential. This article introduces an approach for testing Firebase Cloud Messaging (FCM) using Espresso, focusing on direct interactions with the FirebaseMessagingService.

1. Introducing the FirebasePushNotificationTestRule Class

Central to our approach is the custom JUnit rule named FirebasePushNotificationTestRule. This rule interacts with the lifecycle of FirebaseMessagingService, effectively simulating the reception of push notifications.

class FirebasePushNotificationTestRule(private val pushService: FirebaseMessagingService) : TestWatcher() {

companion object {
private const val FIREBASE_PUSH_TOKEN = "mocked_token_value"
}

override fun starting(description: Description) {
super.starting(description)
pushService.attachBaseContext()
pushService.onCreate()
pushService.onNewToken(FIREBASE_PUSH_TOKEN)
}

override fun finished(description: Description) {
pushService.onDestroy()
super.finished(description)
}

fun onNewToken(token: String) = pushService.onNewToken(token)

fun sendPush(remoteMessage: RemoteMessage) = pushService.onMessageReceived(remoteMessage)
}

2. Exploring the Rule

  • Service Lifecycle Interaction: The rule directly interacts with the lifecycle methods (attachBaseContext(), onCreate(), and onDestroy()) to set up and tear down the service. It is within the onCreate() method where dependency injection typically takes place, ensuring the service is suitably initialized with its necessary dependencies.
internal fun Service.attachBaseContext() {
val context = InstrumentationRegistry.getInstrumentation().targetContext

val attachBaseContextMethod = ContextWrapper::class.java.getDeclaredMethod("attachBaseContext", Context::class.java)
attachBaseContextMethod.isAccessible = true

attachBaseContextMethod.invoke(this, context)
}

- Simulating Push Messages: The rule provides methods (onNewToken and sendPush) to simulate the reception of a new token and a push message.

3. Things to Consider

- Service Dependencies: As dependency injection occurs during onCreate(), ensure that FirebaseMessagingService and its dependencies on shared preferences, databases, or other components are properly configured for testing. Mock or initialize any dependencies as needed to prevent unexpected behavior.

- Using a Mocked Token: The rule uses a mocked token. Depending on the specific testing requirements, this might be sufficient or may need adjustment.

- Granular Testing: The rule can be refined to test different states of the service or various types of push messages.

4. Utilizing the Rule in Tests

To use the FirebasePushNotificationTestRule in your test class:

class FCMInteractionTest {

@get:Rule
val fcmTestRule = FirebasePushNotificationTestRule(FirebaseMessagingService())

@Test
fun testNotificationEffect() {
// Simulate a push message
fcmTestRule.sendPush(mockedRemoteMessage)
// Execute Espresso tests
}
}

5. Conclusion

This approach offers a streamlined way to test FCM interactions in Android applications using Espresso. Ensuring that dependency injection is appropriately managed within the `onCreate()` method is crucial for the successful execution of tests. Combining this approach with other testing strategies can provide comprehensive coverage for push notification functionalities.

--

--

Joseph James (JJ)
Joseph James (JJ)

No responses yet