diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQRCode.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQRCode.kt
index 651c5721e2244a230dd33447a5f6f0896b014279..0c4879f0d4fe082a57b748592d126bf52a412291 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQRCode.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQRCode.kt
@@ -34,9 +34,9 @@ sealed class CoronaTestQRCode : Parcelable, TestRegistrationRequest {
     data class RapidAntigen(
         val hash: RapidAntigenHash,
         val createdAt: Instant,
-        val firstName: String?,
-        val lastName: String?,
-        val dateOfBirth: LocalDate?,
+        val firstName: String? = null,
+        val lastName: String? = null,
+        val dateOfBirth: LocalDate? = null,
     ) : CoronaTestQRCode() {
 
         @IgnoredOnParcel
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/common/TestResultAvailableNotificationService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/common/TestResultAvailableNotificationService.kt
index b6e85bebc655114e7f1b5c25aea02dd645f9c43e..48685eab773107a54f0fa7cc209163e4adaa8108 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/common/TestResultAvailableNotificationService.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/common/TestResultAvailableNotificationService.kt
@@ -22,18 +22,19 @@ open class TestResultAvailableNotificationService(
     private val notificationHelper: GeneralNotifications,
     private val cwaSettings: CWASettings,
     private val notificationId: NotificationId,
+    private val logTag: String,
 ) {
 
     suspend fun showTestResultAvailableNotification(test: CoronaTest) {
-        Timber.d("showTestResultAvailableNotification(test=%s)", test)
+        Timber.tag(logTag).v("showTestResultAvailableNotification(test=%s)", test)
 
         if (foregroundState.isInForeground.first()) {
-            Timber.d("App in foreground, skipping notification.")
+            Timber.tag(logTag).d("App in foreground, skipping notification.")
             return
         }
 
         if (!cwaSettings.isNotificationsTestEnabled.value) {
-            Timber.i("Don't show test result available notification because user doesn't want to be informed")
+            Timber.tag(logTag).i("User has disabled test result notifications.")
             return
         }
 
@@ -63,7 +64,7 @@ open class TestResultAvailableNotificationService(
             setContentIntent(pendingIntent)
         }.build()
 
-        Timber.i("Showing TestResultAvailable notification!")
+        Timber.tag(logTag).i("Showing test result notification($notificationId) for %s", test)
         notificationHelper.sendNotification(
             notificationId = notificationId,
             notification = notification,
@@ -71,6 +72,7 @@ open class TestResultAvailableNotificationService(
     }
 
     fun cancelTestResultAvailableNotification() {
+        Timber.tag(logTag).i("Canceling test result notification($notificationId)")
         notificationHelper.cancelCurrentNotification(notificationId)
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/pcr/PCRProcessor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/pcr/PCRProcessor.kt
index 815401d6e2b1202aa515de4e046d378e0bfb3d0c..03dc9df0aa1f22fbc3a0feaec0263e6465d3b636 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/pcr/PCRProcessor.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/pcr/PCRProcessor.kt
@@ -46,7 +46,9 @@ class PCRProcessor @Inject constructor(
         Timber.tag(TAG).d("create(data=%s)", request)
         request as CoronaTestQRCode.PCR
 
-        val registrationData = submissionService.asyncRegisterDeviceViaGUID(request.qrCodeGUID)
+        val registrationData = submissionService.asyncRegisterDeviceViaGUID(request.qrCodeGUID).also {
+            Timber.tag(TAG).d("Request %s gave us %s", request, it)
+        }
 
         testResultDataCollector.saveTestResultAnalyticsSettings(registrationData.testResult) // This saves received at
 
@@ -72,9 +74,12 @@ class PCRProcessor @Inject constructor(
     ): PCRCoronaTest {
         analyticsKeySubmissionCollector.reset()
 
-        val testResult = response.testResult.validOrThrow()
+        val testResult = response.testResult.let {
+            Timber.tag(TAG).v("Raw test result $it")
+            testResultDataCollector.updatePendingTestResultReceivedTime(it)
 
-        testResultDataCollector.updatePendingTestResultReceivedTime(testResult)
+            it.toValidatedResult()
+        }
 
         if (testResult == PCR_POSITIVE) {
             analyticsKeySubmissionCollector.reportPositiveTestResultReceived()
@@ -105,12 +110,12 @@ class PCRProcessor @Inject constructor(
                 return test
             }
 
-            val newTestResult = submissionService.asyncRequestTestResult(test.registrationToken)
-            Timber.tag(TAG).d("Test result was %s", newTestResult)
-
-            newTestResult.validOrThrow()
+            val newTestResult = submissionService.asyncRequestTestResult(test.registrationToken).let {
+                Timber.tag(TAG).d("Raw test result was %s", it)
+                testResultDataCollector.updatePendingTestResultReceivedTime(it)
 
-            testResultDataCollector.updatePendingTestResultReceivedTime(newTestResult)
+                it.toValidatedResult()
+            }
 
             if (newTestResult == PCR_POSITIVE) {
                 analyticsKeySubmissionCollector.reportPositiveTestResultReceived()
@@ -193,11 +198,11 @@ class PCRProcessor @Inject constructor(
 
     companion object {
         private val FINAL_STATES = setOf(PCR_POSITIVE, PCR_NEGATIVE, PCR_REDEEMED)
-        private const val TAG = "PCRProcessor"
+        internal const val TAG = "PCRProcessor"
     }
 }
 
-private fun CoronaTestResult.validOrThrow(): CoronaTestResult {
+private fun CoronaTestResult.toValidatedResult(): CoronaTestResult {
     val isValid = when (this) {
         PCR_OR_RAT_PENDING,
         PCR_NEGATIVE,
@@ -212,6 +217,10 @@ private fun CoronaTestResult.validOrThrow(): CoronaTestResult {
         RAT_REDEEMED -> false
     }
 
-    if (!isValid) throw IllegalArgumentException("Invalid testResult $this")
-    return this
+    return if (isValid) {
+        this
+    } else {
+        Timber.tag(PCRProcessor.TAG).e("Server returned invalid PCR testresult $this")
+        PCR_INVALID
+    }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/pcr/notification/PCRTestResultAvailableNotificationService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/pcr/notification/PCRTestResultAvailableNotificationService.kt
index d8d631cb6882dac0f50ed6f9592be76f620ec28c..1a2dd6872c13a09509dd74816e9bae3b6f8dbb1a 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/pcr/notification/PCRTestResultAvailableNotificationService.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/pcr/notification/PCRTestResultAvailableNotificationService.kt
@@ -36,31 +36,43 @@ class PCRTestResultAvailableNotificationService @Inject constructor(
     navDeepLinkBuilderProvider,
     notificationHelper,
     cwaSettings,
-    NotificationConstants.PCR_TEST_RESULT_AVAILABLE_NOTIFICATION_ID
+    NotificationConstants.PCR_TEST_RESULT_AVAILABLE_NOTIFICATION_ID,
+    logTag = TAG,
 ) {
+
     fun setup() {
         Timber.tag(TAG).d("setup() - PCRTestResultAvailableNotificationService")
 
+        @Suppress("RedundantLambdaArrow")
         coronaTestRepository.latestPCRT
             .onEach { _ ->
+                // We want the flow to trigger us, but not work with outdated data due to queue processing
                 val test = coronaTestRepository.latestPCRT.first()
+                Timber.tag(TAG).v("PCR test change: %s", test)
+
                 if (test == null) {
                     cancelTestResultAvailableNotification()
                     return@onEach
                 }
 
-                val alreadySent = test.isResultAvailableNotificationSent
+                val notSentYet = !test.isResultAvailableNotificationSent
                 val isInteresting = INTERESTING_STATES.contains(test.testResult)
-                Timber.tag(TAG).v("alreadySent=$alreadySent, isInteresting=$isInteresting")
+                val isTestViewed = test.isViewed
+                Timber.tag(TAG).v("notSentYet=$notSentYet, isInteresting=$isInteresting, isTestViewed=$isTestViewed")
 
-                if (!alreadySent && isInteresting) {
-                    coronaTestRepository.updateResultNotification(identifier = test.identifier, sent = true)
-                    showTestResultAvailableNotification(test)
-                    notificationHelper.cancelCurrentNotification(
-                        NotificationConstants.NEW_MESSAGE_RISK_LEVEL_SCORE_NOTIFICATION_ID
-                    )
-                } else {
-                    cancelTestResultAvailableNotification()
+                when {
+                    notSentYet && isInteresting -> {
+                        Timber.tag(TAG).d("Showing PCR test result notification.")
+                        showTestResultAvailableNotification(test)
+                        coronaTestRepository.updateResultNotification(identifier = test.identifier, sent = true)
+                        notificationHelper.cancelCurrentNotification(
+                            NotificationConstants.NEW_MESSAGE_RISK_LEVEL_SCORE_NOTIFICATION_ID
+                        )
+                    }
+                    isTestViewed -> {
+                        Timber.tag(TAG).d("Canceling PCR test result notification.")
+                        cancelTestResultAvailableNotification()
+                    }
                 }
             }
             .launchIn(appScope)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/rapidantigen/RapidAntigenProcessor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/rapidantigen/RapidAntigenProcessor.kt
index 9454ce480a3b245046b45d89fa89be69281cf4bd..2a9d412af608b844ebea4b85bbc209f10e14171d 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/rapidantigen/RapidAntigenProcessor.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/rapidantigen/RapidAntigenProcessor.kt
@@ -39,9 +39,14 @@ class RapidAntigenProcessor @Inject constructor(
         Timber.tag(TAG).d("create(data=%s)", request)
         request as CoronaTestQRCode.RapidAntigen
 
-        val registrationData = submissionService.asyncRegisterDeviceViaGUID(request.registrationIdentifier)
+        val registrationData = submissionService.asyncRegisterDeviceViaGUID(request.registrationIdentifier).also {
+            Timber.tag(TAG).d("Request %s gave us %s", request, it)
+        }
 
-        val testResult = registrationData.testResult.validOrThrow()
+        val testResult = registrationData.testResult.let {
+            Timber.tag(TAG).v("Raw test result was %s", it)
+            it.toValidatedResult()
+        }
 
         val now = timeStamper.nowUTC
 
@@ -81,8 +86,10 @@ class RapidAntigenProcessor @Inject constructor(
                 return test
             }
 
-            val newTestResult = submissionService.asyncRequestTestResult(test.registrationToken)
-            Timber.tag(TAG).d("Test result was %s", newTestResult)
+            val newTestResult = submissionService.asyncRequestTestResult(test.registrationToken).let {
+                Timber.tag(TAG).v("Raw test result was %s", it)
+                it.toValidatedResult()
+            }
 
             test.copy(
                 testResult = check60PlusDays(test, newTestResult),
@@ -157,11 +164,11 @@ class RapidAntigenProcessor @Inject constructor(
 
     companion object {
         private val FINAL_STATES = setOf(RAT_POSITIVE, RAT_NEGATIVE, RAT_REDEEMED)
-        private const val TAG = "RapidAntigenProcessor"
+        internal const val TAG = "RapidAntigenProcessor"
     }
 }
 
-private fun CoronaTestResult.validOrThrow(): CoronaTestResult {
+private fun CoronaTestResult.toValidatedResult(): CoronaTestResult {
     val isValid = when (this) {
         PCR_OR_RAT_PENDING,
         RAT_PENDING,
@@ -176,6 +183,10 @@ private fun CoronaTestResult.validOrThrow(): CoronaTestResult {
         PCR_REDEEMED -> false
     }
 
-    if (!isValid) throw IllegalArgumentException("Invalid testResult $this")
-    return this
+    return if (isValid) {
+        this
+    } else {
+        Timber.tag(RapidAntigenProcessor.TAG).e("Server returned invalid RapidAntigen testresult $this")
+        RAT_INVALID
+    }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/rapidantigen/notification/RATTestResultAvailableNotificationService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/rapidantigen/notification/RATTestResultAvailableNotificationService.kt
index b7d5a0886b296ad610d713b5f1c5c798093e775a..49fd8b04f991b4596609052462ea70fa4e9bb9aa 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/rapidantigen/notification/RATTestResultAvailableNotificationService.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/rapidantigen/notification/RATTestResultAvailableNotificationService.kt
@@ -3,7 +3,6 @@ package de.rki.coronawarnapp.coronatest.type.rapidantigen.notification
 import android.content.Context
 import androidx.navigation.NavDeepLinkBuilder
 import de.rki.coronawarnapp.coronatest.CoronaTestRepository
-import de.rki.coronawarnapp.coronatest.latestPCRT
 import de.rki.coronawarnapp.coronatest.latestRAT
 import de.rki.coronawarnapp.coronatest.server.CoronaTestResult
 import de.rki.coronawarnapp.coronatest.type.common.TestResultAvailableNotificationService
@@ -38,30 +37,41 @@ class RATTestResultAvailableNotificationService @Inject constructor(
     notificationHelper,
     cwaSettings,
     NotificationConstants.RAT_TEST_RESULT_AVAILABLE_NOTIFICATION_ID,
+    logTag = TAG,
 ) {
     fun setup() {
         Timber.tag(TAG).d("setup() - RATTestResultAvailableNotificationService")
 
-        coronaTestRepository.latestPCRT
+        @Suppress("RedundantLambdaArrow")
+        coronaTestRepository.latestRAT
             .onEach { _ ->
+                // We want the flow to trigger us, but not work with outdated data due to queue processing
                 val test = coronaTestRepository.latestRAT.first()
+                Timber.tag(TAG).v("RA test change: %s", test)
+
                 if (test == null) {
                     cancelTestResultAvailableNotification()
                     return@onEach
                 }
 
-                val alreadySent = test.isResultAvailableNotificationSent
+                val notSentYet = !test.isResultAvailableNotificationSent
                 val isInteresting = INTERESTING_STATES.contains(test.testResult)
-                Timber.tag(TAG).v("alreadySent=$alreadySent, isInteresting=$isInteresting")
+                val isTestViewed = test.isViewed
+                Timber.tag(TAG).v("notSentYet=$notSentYet, isInteresting=$isInteresting, isTestViewed=$isTestViewed")
 
-                if (!alreadySent && isInteresting) {
-                    coronaTestRepository.updateResultNotification(identifier = test.identifier, sent = true)
-                    showTestResultAvailableNotification(test)
-                    notificationHelper.cancelCurrentNotification(
-                        NotificationConstants.NEW_MESSAGE_RISK_LEVEL_SCORE_NOTIFICATION_ID
-                    )
-                } else {
-                    cancelTestResultAvailableNotification()
+                when {
+                    notSentYet && isInteresting -> {
+                        Timber.tag(TAG).d("Showing RA test result notification.")
+                        showTestResultAvailableNotification(test)
+                        coronaTestRepository.updateResultNotification(identifier = test.identifier, sent = true)
+                        notificationHelper.cancelCurrentNotification(
+                            NotificationConstants.NEW_MESSAGE_RISK_LEVEL_SCORE_NOTIFICATION_ID
+                        )
+                    }
+                    isTestViewed -> {
+                        Timber.tag(TAG).d("Canceling RA test result notification as it has already been viewed.")
+                        cancelTestResultAvailableNotification()
+                    }
                 }
             }
             .launchIn(appScope)
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/type/pcr/PCRProcessorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/type/pcr/PCRProcessorTest.kt
index 2028ef505b309a63ec1c202f7f045812203b970e..9f07dc1959de84bd42eb0760ac77689f9abf301d 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/type/pcr/PCRProcessorTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/type/pcr/PCRProcessorTest.kt
@@ -2,6 +2,17 @@ package de.rki.coronawarnapp.coronatest.type.pcr
 
 import de.rki.coronawarnapp.coronatest.qrcode.CoronaTestQRCode
 import de.rki.coronawarnapp.coronatest.server.CoronaTestResult
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.PCR_INVALID
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.PCR_NEGATIVE
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.PCR_OR_RAT_PENDING
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.PCR_POSITIVE
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.PCR_REDEEMED
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.RAT_INVALID
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.RAT_NEGATIVE
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.RAT_PENDING
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.RAT_POSITIVE
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.RAT_REDEEMED
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.values
 import de.rki.coronawarnapp.coronatest.tan.CoronaTestTAN
 import de.rki.coronawarnapp.coronatest.type.CoronaTestService
 import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
@@ -21,6 +32,7 @@ import org.joda.time.Instant
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import testhelpers.BaseTest
+import timber.log.Timber
 
 class PCRProcessorTest : BaseTest() {
     @MockK lateinit var timeStamper: TimeStamper
@@ -31,15 +43,6 @@ class PCRProcessorTest : BaseTest() {
 
     private val nowUTC = Instant.parse("2021-03-15T05:45:00.000Z")
 
-    private var testQRRegistrationData = CoronaTestService.RegistrationData(
-        registrationToken = "qr-regtoken",
-        testResult = CoronaTestResult.PCR_POSITIVE,
-    )
-    private var testTANRegistrationData = CoronaTestService.RegistrationData(
-        registrationToken = "tan-regtoken",
-        testResult = CoronaTestResult.PCR_POSITIVE,
-    )
-
     @BeforeEach
     fun setup() {
         MockKAnnotations.init(this)
@@ -47,9 +50,15 @@ class PCRProcessorTest : BaseTest() {
         every { timeStamper.nowUTC } returns nowUTC
 
         submissionService.apply {
-            coEvery { asyncRequestTestResult(any()) } answers { CoronaTestResult.PCR_OR_RAT_PENDING }
-            coEvery { asyncRegisterDeviceViaTAN(any()) } answers { testTANRegistrationData }
-            coEvery { asyncRegisterDeviceViaGUID(any()) } answers { testQRRegistrationData }
+            coEvery { asyncRequestTestResult(any()) } returns PCR_OR_RAT_PENDING
+            coEvery { asyncRegisterDeviceViaGUID(any()) } returns CoronaTestService.RegistrationData(
+                registrationToken = "regtoken-qr",
+                testResult = PCR_OR_RAT_PENDING,
+            )
+            coEvery { asyncRegisterDeviceViaTAN(any()) } returns CoronaTestService.RegistrationData(
+                registrationToken = "regtoken-tan",
+                testResult = PCR_OR_RAT_PENDING,
+            )
         }
 
         analyticsKeySubmissionCollector.apply {
@@ -84,16 +93,85 @@ class PCRProcessorTest : BaseTest() {
             lastUpdatedAt = Instant.EPOCH,
             registeredAt = nowUTC,
             registrationToken = "regtoken",
-            testResult = CoronaTestResult.PCR_POSITIVE
+            testResult = PCR_POSITIVE
         )
 
-        instance.pollServer(pcrTest).testResult shouldBe CoronaTestResult.PCR_OR_RAT_PENDING
+        instance.pollServer(pcrTest).testResult shouldBe PCR_OR_RAT_PENDING
 
         val past60DaysTest = pcrTest.copy(
             registeredAt = nowUTC.minus(Duration.standardDays(21))
         )
 
-        instance.pollServer(past60DaysTest).testResult shouldBe CoronaTestResult.PCR_REDEEMED
+        instance.pollServer(past60DaysTest).testResult shouldBe PCR_REDEEMED
+    }
+
+    @Test
+    fun `registering a new test maps invalid results to INVALID state`() = runBlockingTest {
+        var registrationData = CoronaTestService.RegistrationData(
+            registrationToken = "regtoken",
+            testResult = PCR_OR_RAT_PENDING,
+        )
+        coEvery { submissionService.asyncRegisterDeviceViaGUID(any()) } answers { registrationData }
+
+        val instance = createInstance()
+
+        val request = CoronaTestQRCode.PCR(qrCodeGUID = "guid")
+
+        values().forEach {
+            registrationData = registrationData.copy(testResult = it)
+            when (it) {
+                PCR_OR_RAT_PENDING,
+                PCR_NEGATIVE,
+                PCR_POSITIVE,
+                PCR_INVALID,
+                PCR_REDEEMED -> instance.create(request).testResult shouldBe it
+
+                RAT_PENDING,
+                RAT_NEGATIVE,
+                RAT_POSITIVE,
+                RAT_INVALID,
+                RAT_REDEEMED ->
+                    instance.create(request).testResult shouldBe PCR_INVALID
+            }
+        }
+    }
+
+    @Test
+    fun `polling maps invalid results to INVALID state`() = runBlockingTest {
+        var pollResult: CoronaTestResult = PCR_OR_RAT_PENDING
+        coEvery { submissionService.asyncRequestTestResult(any()) } answers { pollResult }
+
+        val instance = createInstance()
+
+        val pcrTest = PCRCoronaTest(
+            identifier = "identifier",
+            lastUpdatedAt = Instant.EPOCH,
+            registeredAt = nowUTC,
+            registrationToken = "regtoken",
+            testResult = PCR_POSITIVE
+        )
+
+        values().forEach {
+            pollResult = it
+            when (it) {
+                PCR_OR_RAT_PENDING,
+                PCR_NEGATIVE,
+                PCR_POSITIVE,
+                PCR_INVALID,
+                PCR_REDEEMED -> {
+                    Timber.v("Should NOT throw for $it")
+                    instance.pollServer(pcrTest).testResult shouldBe it
+                }
+                RAT_PENDING,
+                RAT_NEGATIVE,
+                RAT_POSITIVE,
+                RAT_INVALID,
+                RAT_REDEEMED -> {
+                    Timber.v("Should throw for $it")
+                    instance.pollServer(pcrTest).testResult shouldBe PCR_INVALID
+                }
+            }
+        }
     }
 
     // TANs are automatically positive, there is no test result available screen that should be reached
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/type/rapidantigen/RapidAntigenProcessorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/type/rapidantigen/RapidAntigenProcessorTest.kt
index b2b3693be4be5f6d4bca10a5c0ed201df0116d87..76573d88bc5c0dbfe14a727593fa4b37f1e2e55a 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/type/rapidantigen/RapidAntigenProcessorTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/type/rapidantigen/RapidAntigenProcessorTest.kt
@@ -1,6 +1,18 @@
 package de.rki.coronawarnapp.coronatest.type.rapidantigen
 
+import de.rki.coronawarnapp.coronatest.qrcode.CoronaTestQRCode
 import de.rki.coronawarnapp.coronatest.server.CoronaTestResult
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.PCR_INVALID
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.PCR_NEGATIVE
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.PCR_OR_RAT_PENDING
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.PCR_POSITIVE
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.PCR_REDEEMED
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.RAT_INVALID
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.RAT_NEGATIVE
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.RAT_PENDING
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.RAT_POSITIVE
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.RAT_REDEEMED
+import de.rki.coronawarnapp.coronatest.server.CoronaTestResult.values
 import de.rki.coronawarnapp.coronatest.type.CoronaTestService
 import de.rki.coronawarnapp.util.TimeStamper
 import io.kotest.matchers.shouldBe
@@ -29,7 +41,15 @@ class RapidAntigenProcessorTest : BaseTest() {
         every { timeStamper.nowUTC } returns nowUTC
 
         submissionService.apply {
-            coEvery { asyncRequestTestResult(any()) } answers { CoronaTestResult.PCR_OR_RAT_PENDING }
+            coEvery { asyncRequestTestResult(any()) } returns PCR_OR_RAT_PENDING
+            coEvery { asyncRegisterDeviceViaGUID(any()) } returns CoronaTestService.RegistrationData(
+                registrationToken = "regtoken-qr",
+                testResult = PCR_OR_RAT_PENDING,
+            )
+            coEvery { asyncRegisterDeviceViaTAN(any()) } returns CoronaTestService.RegistrationData(
+                registrationToken = "regtoken-tan",
+                testResult = PCR_OR_RAT_PENDING,
+            )
         }
     }
 
@@ -42,21 +62,88 @@ class RapidAntigenProcessorTest : BaseTest() {
     fun `if we receive a pending result 60 days after registration, we map to REDEEMED`() = runBlockingTest {
         val instance = createInstance()
 
-        val pcrTest = RACoronaTest(
+        val raTest = RACoronaTest(
             identifier = "identifier",
             lastUpdatedAt = Instant.EPOCH,
             registeredAt = nowUTC,
             registrationToken = "regtoken",
-            testResult = CoronaTestResult.RAT_POSITIVE,
+            testResult = RAT_POSITIVE,
             testedAt = Instant.EPOCH,
         )
 
-        instance.pollServer(pcrTest).testResult shouldBe CoronaTestResult.PCR_OR_RAT_PENDING
+        instance.pollServer(raTest).testResult shouldBe PCR_OR_RAT_PENDING
 
-        val past60DaysTest = pcrTest.copy(
+        val past60DaysTest = raTest.copy(
             registeredAt = nowUTC.minus(Duration.standardDays(21))
         )
 
-        instance.pollServer(past60DaysTest).testResult shouldBe CoronaTestResult.RAT_REDEEMED
+        instance.pollServer(past60DaysTest).testResult shouldBe RAT_REDEEMED
+    }
+
+    @Test
+    fun `registering a new test maps invalid results to INVALID state`() = runBlockingTest {
+        var registrationData = CoronaTestService.RegistrationData(
+            registrationToken = "regtoken",
+            testResult = PCR_OR_RAT_PENDING,
+        )
+        coEvery { submissionService.asyncRegisterDeviceViaGUID(any()) } answers { registrationData }
+
+        val instance = createInstance()
+
+        val request = CoronaTestQRCode.RapidAntigen(
+            hash = "hash",
+            createdAt = Instant.EPOCH,
+        )
+
+        values().forEach {
+            registrationData = registrationData.copy(testResult = it)
+            when (it) {
+                PCR_NEGATIVE,
+                PCR_POSITIVE,
+                PCR_INVALID,
+                PCR_REDEEMED -> instance.create(request).testResult shouldBe RAT_INVALID
+
+                PCR_OR_RAT_PENDING,
+                RAT_PENDING,
+                RAT_NEGATIVE,
+                RAT_POSITIVE,
+                RAT_INVALID,
+                RAT_REDEEMED -> instance.create(request).testResult shouldBe it
+            }
+        }
+    }
+
+    @Test
+    fun `polling filters out invalid test result values`() = runBlockingTest {
+        var pollResult: CoronaTestResult = PCR_OR_RAT_PENDING
+        coEvery { submissionService.asyncRequestTestResult(any()) } answers { pollResult }
+
+        val instance = createInstance()
+
+        val raTest = RACoronaTest(
+            identifier = "identifier",
+            lastUpdatedAt = Instant.EPOCH,
+            registeredAt = nowUTC,
+            registrationToken = "regtoken",
+            testResult = RAT_POSITIVE,
+            testedAt = Instant.EPOCH,
+        )
+
+        values().forEach {
+            pollResult = it
+            when (it) {
+                PCR_NEGATIVE,
+                PCR_POSITIVE,
+                PCR_INVALID,
+                PCR_REDEEMED -> instance.pollServer(raTest).testResult shouldBe RAT_INVALID
+
+                PCR_OR_RAT_PENDING,
+                RAT_PENDING,
+                RAT_NEGATIVE,
+                RAT_POSITIVE,
+                RAT_INVALID,
+                RAT_REDEEMED -> instance.pollServer(raTest).testResult shouldBe it
+            }
+        }
     }
 }