Fix Android notification service code review issues

- Fix invalid notificationManager extension property (line 60)
- Remove invalid getChannelId() calls (line 124)
- Fix NotificationCompat.Builder to use method chaining (line 140)
- Remove undefined newIntent() call (line 154)
- Add unit tests for NotificationService, NotificationManager, NotificationPreferences

All fixes address issues identified in code review for FRE-536.
This commit is contained in:
2026-03-31 06:24:19 -04:00
parent f8d696a440
commit 9ce750bed6
3 changed files with 486 additions and 14 deletions

View File

@@ -0,0 +1,188 @@
package com.rssuper.services
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.PermissionGrantState
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.doReturn
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.verify
import com.nhaarman.mockitokotlin2.whenever
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [Build.VERSION_CODES.TIRAMISU])
class NotificationServiceTest {
private lateinit var context: Context
private lateinit var notificationManager: NotificationManager
private lateinit var notificationService: NotificationService
@Before
fun setup() {
context = mock()
notificationManager = mock()
notificationService = NotificationService(context)
}
@Test
fun testCreateNotificationChannels_OreoPlus() = runTest {
whenever(context.getSystemService(Context.NOTIFICATION_SERVICE))
.doReturn(notificationManager)
notificationService.createNotificationChannels()
verify(notificationManager).createNotificationChannel(any<NotificationChannel>())
}
@Test
fun testHasNotificationPermission_belowTiramisu() = runTest {
whenever(context.checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS))
.doReturn(PackageManager.PERMISSION_GRANTED)
val hasPermission = notificationService.hasNotificationPermission()
assertTrue(hasPermission)
}
@Test
fun testHasNotificationPermission_granted() = runTest {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
whenever(context.checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS))
.doReturn(PackageManager.PERMISSION_GRANTED)
val hasPermission = notificationService.hasNotificationPermission()
assertTrue(hasPermission)
}
}
@Test
fun testHasNotificationPermission_denied() = runTest {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
whenever(context.checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS))
.doReturn(PackageManager.PERMISSION_DENIED)
val hasPermission = notificationService.hasNotificationPermission()
assertFalse(hasPermission)
}
}
@Test
fun testShowNotification_permissionGranted() = runTest {
val mockNotificationManager = mock<NotificationManagerCompat>()
whenever(NotificationManagerCompat.from(context)).doReturn(mockNotificationManager)
whenever(mockNotificationManager.notify(any<Int>(), any<Notification>())).doReturn(true)
val result = notificationService.showNotification("Test Title", "Test Body")
assertTrue(result)
}
@Test
fun testShowNotification_permissionDenied() = runTest {
val mockNotificationManager = mock<NotificationManagerCompat>()
whenever(NotificationManagerCompat.from(context)).doReturn(mockNotificationManager)
whenever(mockNotificationManager.notify(any<Int>(), any<Notification>())).doReturn(false)
val result = notificationService.showNotification("Test Title", "Test Body")
assertFalse(result)
}
@Test
fun testShowLocalNotification() = runTest {
val mockNotificationManager = mock<NotificationManagerCompat>()
whenever(NotificationManagerCompat.from(context)).doReturn(mockNotificationManager)
whenever(mockNotificationManager.notify(any<Int>(), any<Notification>())).doReturn(true)
val result = notificationService.showLocalNotification("Test Title", "Test Body")
assertTrue(result)
}
@Test
fun testShowPushNotification() = runTest {
val mockNotificationManager = mock<NotificationManagerCompat>()
whenever(NotificationManagerCompat.from(context)).doReturn(mockNotificationManager)
whenever(mockNotificationManager.notify(any<Int>(), any<Notification>())).doReturn(true)
val result = notificationService.showPushNotification("Test Title", "Test Body")
assertTrue(result)
}
@Test
fun testShowNotificationWithAction() = runTest {
val mockNotificationManager = mock<NotificationManagerCompat>()
whenever(NotificationManagerCompat.from(context)).doReturn(mockNotificationManager)
whenever(mockNotificationManager.notify(any<Int>(), any<Notification>())).doReturn(true)
val actionIntent: Intent = mock()
val result = notificationService.showNotificationWithAction(
"Test Title",
"Test Body",
"Action Label",
PendingIntent.getActivity(context, 0, actionIntent, PendingIntent.FLAG_IMMUTABLE)
)
assertTrue(result)
}
@Test
fun testUpdateBadgeCount() = runTest {
notificationService.updateBadgeCount(5)
}
@Test
fun testClearAllNotifications() = runTest {
val mockNotificationManager = mock<NotificationManager>()
whenever(context.getSystemService(Context.NOTIFICATION_SERVICE))
.doReturn(mockNotificationManager)
notificationService.clearAllNotifications()
verify(mockNotificationManager).cancelAll()
}
@Test
fun testGetPreferences() = runTest {
val preferences = notificationService.getPreferences()
assertNotNull(preferences)
assertEquals(true, preferences.newArticles)
assertEquals(true, preferences.episodeReleases)
}
@Test
fun testSavePreferences() = runTest {
val preferences = NotificationPreferences(
newArticles = true,
episodeReleases = false
)
notificationService.savePreferences(preferences)
val retrieved = notificationService.getPreferences()
assertEquals(true, retrieved.newArticles)
assertEquals(false, retrieved.episodeReleases)
}
}