diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/encryptionmigration/EncryptedPreferencesMigration.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/encryptionmigration/EncryptedPreferencesMigration.kt
index 1413fb640b79db0c2a5d3ff21ef32606428e30d3..e5f9d81677ee0a601b55e6c9205ddda7050d228a 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/encryptionmigration/EncryptedPreferencesMigration.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/encryptionmigration/EncryptedPreferencesMigration.kt
@@ -3,6 +3,7 @@ package de.rki.coronawarnapp.util.encryptionmigration
 import android.content.Context
 import android.content.SharedPreferences
 import android.database.sqlite.SQLiteDatabase
+import androidx.annotation.VisibleForTesting
 import de.rki.coronawarnapp.bugreporting.reportProblem
 import de.rki.coronawarnapp.main.CWASettings
 import de.rki.coronawarnapp.storage.OnboardingSettings
@@ -97,7 +98,8 @@ class EncryptedPreferencesMigration @Inject constructor(
         }
     }
 
-    private class SettingsLocalData(private val sharedPreferences: SharedPreferences) {
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    class SettingsLocalData(private val sharedPreferences: SharedPreferences) {
 
         fun wasInteroperabilityShown() = sharedPreferences.getBoolean(PREFERENCE_INTEROPERABILITY_WAS_USED, false)
 
@@ -109,15 +111,22 @@ class EncryptedPreferencesMigration @Inject constructor(
             sharedPreferences.getInt(PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT, Int.MIN_VALUE)
 
         companion object {
-            private const val PREFERENCE_INTEROPERABILITY_WAS_USED = "preference_interoperability_is_used_at_least_once"
-            private const val PKEY_NOTIFICATIONS_RISK_ENABLED = "preference_notifications_risk_enabled"
-            private const val PKEY_NOTIFICATIONS_TEST_ENABLED = "preference_notifications_test_enabled"
-            private const val PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT =
-                "preference_positive_test_result_reminder_count"
+            @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+            const val PREFERENCE_INTEROPERABILITY_WAS_USED = "preference_interoperability_is_used_at_least_once"
+
+            @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+            const val PKEY_NOTIFICATIONS_RISK_ENABLED = "preference_notifications_risk_enabled"
+
+            @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+            const val PKEY_NOTIFICATIONS_TEST_ENABLED = "preference_notifications_test_enabled"
+
+            @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+            const val PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT = "preference_positive_test_result_reminder_count"
         }
     }
 
-    private class OnboardingLocalData(private val sharedPreferences: SharedPreferences) {
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    class OnboardingLocalData(private val sharedPreferences: SharedPreferences) {
         fun onboardingCompletedTimestamp(): Long? {
             val timestamp = sharedPreferences.getLong(PKEY_ONBOARDING_COMPLETED_TIMESTAMP, 0L)
 
@@ -128,12 +137,16 @@ class EncryptedPreferencesMigration @Inject constructor(
         fun isBackgroundCheckDone(): Boolean = sharedPreferences.getBoolean(PKEY_BACKGROUND_CHECK_DONE, false)
 
         companion object {
-            private const val PKEY_ONBOARDING_COMPLETED_TIMESTAMP = "preference_onboarding_completed_timestamp"
-            private const val PKEY_BACKGROUND_CHECK_DONE = "preference_background_check_done"
+            @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+            const val PKEY_ONBOARDING_COMPLETED_TIMESTAMP = "preference_onboarding_completed_timestamp"
+
+            @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+            const val PKEY_BACKGROUND_CHECK_DONE = "preference_background_check_done"
         }
     }
 
-    private class TracingLocalData(private val sharedPreferences: SharedPreferences) {
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    class TracingLocalData(private val sharedPreferences: SharedPreferences) {
 
         fun initialPollingForTestResultTimeStamp() = sharedPreferences.getLong(PKEY_POOLING_TEST_RESULT_STARTED, 0L)
 
@@ -144,14 +157,22 @@ class EncryptedPreferencesMigration @Inject constructor(
         fun initialTracingActivationTimestamp(): Long = sharedPreferences.getLong(PKEY_TRACING_ACTIVATION_TIME, 0L)
 
         companion object {
-            private const val PKEY_POOLING_TEST_RESULT_STARTED = "preference_polling_test_result_started"
-            private const val PKEY_TEST_RESULT_NOTIFICATION = "preference_test_result_notification"
-            private const val PKEY_HAS_RISK_STATUS_LOWERED = "preference_has_risk_status_lowered"
-            private const val PKEY_TRACING_ACTIVATION_TIME = "preference_initial_tracing_activation_time"
+            @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+            const val PKEY_POOLING_TEST_RESULT_STARTED = "preference_polling_test_result_started"
+
+            @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+            const val PKEY_TEST_RESULT_NOTIFICATION = "preference_test_result_notification"
+
+            @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+            const val PKEY_HAS_RISK_STATUS_LOWERED = "preference_has_risk_status_lowered"
+
+            @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+            const val PKEY_TRACING_ACTIVATION_TIME = "preference_initial_tracing_activation_time"
         }
     }
 
-    private class SubmissionLocalData(private val sharedPreferences: SharedPreferences) {
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    class SubmissionLocalData(private val sharedPreferences: SharedPreferences) {
         fun registrationToken(): String? = sharedPreferences.getString(PKEY_REGISTRATION_TOKEN, null)
 
         fun initialTestResultReceivedTimestamp(): Long? {
@@ -168,11 +189,20 @@ class EncryptedPreferencesMigration @Inject constructor(
         fun isAllowedToSubmitDiagnosisKeys(): Boolean = sharedPreferences.getBoolean(PKEY_IS_ALLOWED_TO_SUBMIT, false)
 
         companion object {
-            private const val PKEY_REGISTRATION_TOKEN = "preference_registration_token"
-            private const val PKEY_INITIAL_RESULT_RECEIVED_TIME = "preference_initial_result_received_time"
-            private const val PKEY_DEVICE_PARING_SUCCESSFUL_TIME = "preference_device_pairing_successful_time"
-            private const val PKEY_NUMBER_SUCCESSFUL_SUBMISSIONS = "preference_number_successful_submissions"
-            private const val PKEY_IS_ALLOWED_TO_SUBMIT = "preference_is_allowed_to_submit_diagnosis_keys"
+            @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+            const val PKEY_REGISTRATION_TOKEN = "preference_registration_token"
+
+            @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+            const val PKEY_INITIAL_RESULT_RECEIVED_TIME = "preference_initial_result_received_time"
+
+            @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+            const val PKEY_DEVICE_PARING_SUCCESSFUL_TIME = "preference_device_pairing_successful_time"
+
+            @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+            const val PKEY_NUMBER_SUCCESSFUL_SUBMISSIONS = "preference_number_successful_submissions"
+
+            @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+            const val PKEY_IS_ALLOWED_TO_SUBMIT = "preference_is_allowed_to_submit_diagnosis_keys"
         }
     }
 }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/encryptionmigration/EncryptedPreferencesMigrationTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/encryptionmigration/EncryptedPreferencesMigrationTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c4b671d9e27857ea7738ea1bf37adce39273d4fc
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/encryptionmigration/EncryptedPreferencesMigrationTest.kt
@@ -0,0 +1,163 @@
+package de.rki.coronawarnapp.util.encryptionmigration
+
+import android.content.Context
+import android.content.SharedPreferences
+import androidx.core.content.edit
+import de.rki.coronawarnapp.main.CWASettings
+import de.rki.coronawarnapp.storage.OnboardingSettings
+import de.rki.coronawarnapp.storage.TracingSettings
+import de.rki.coronawarnapp.submission.SubmissionSettings
+import io.kotest.assertions.throwables.shouldNotThrowAny
+import io.kotest.matchers.shouldBe
+import io.mockk.MockKAnnotations
+import io.mockk.Runs
+import io.mockk.every
+import io.mockk.impl.annotations.MockK
+import io.mockk.just
+import io.mockk.mockk
+import org.joda.time.Instant
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import testhelpers.BaseIOTest
+import testhelpers.preferences.MockSharedPreferences
+import testhelpers.preferences.mockFlowPreference
+import java.io.File
+
+class EncryptedPreferencesMigrationTest : BaseIOTest() {
+    @MockK lateinit var context: Context
+    @MockK lateinit var encryptedPreferencesHelper: EncryptedPreferencesHelper
+    @MockK lateinit var cwaSettings: CWASettings
+    @MockK lateinit var submissionSettings: SubmissionSettings
+    @MockK lateinit var tracingSettings: TracingSettings
+    @MockK lateinit var onboardingSettings: OnboardingSettings
+    @MockK lateinit var encryptedErrorResetTool: EncryptionErrorResetTool
+
+    private val testDir = File(IO_TEST_BASEDIR, this::class.java.simpleName)
+    private val dbFile = File(testDir, "database.sql")
+
+    @BeforeEach
+    fun setup() {
+        MockKAnnotations.init(this)
+
+        testDir.mkdirs()
+    }
+
+    @AfterEach
+    fun teardown() {
+        testDir.deleteRecursively()
+    }
+
+    private fun createInstance() = EncryptedPreferencesMigration(
+        context = context,
+        encryptedPreferences = encryptedPreferencesHelper,
+        cwaSettings = cwaSettings,
+        submissionSettings = submissionSettings,
+        tracingSettings = tracingSettings,
+        onboardingSettings = onboardingSettings,
+        errorResetTool = encryptedErrorResetTool
+    )
+
+    private fun createOldPreferences() = MockSharedPreferences().also {
+        it.edit {
+            // SettingsLocalData
+            putBoolean(EncryptedPreferencesMigration.SettingsLocalData.PREFERENCE_INTEROPERABILITY_WAS_USED, true)
+            putBoolean(EncryptedPreferencesMigration.SettingsLocalData.PKEY_NOTIFICATIONS_RISK_ENABLED, false)
+            putBoolean(EncryptedPreferencesMigration.SettingsLocalData.PKEY_NOTIFICATIONS_TEST_ENABLED, false)
+            putInt(
+                EncryptedPreferencesMigration.SettingsLocalData.PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT,
+                Int.MAX_VALUE
+            )
+
+            // OnboardingLocalData
+            putLong(EncryptedPreferencesMigration.OnboardingLocalData.PKEY_ONBOARDING_COMPLETED_TIMESTAMP, 10101010L)
+            putBoolean(EncryptedPreferencesMigration.OnboardingLocalData.PKEY_BACKGROUND_CHECK_DONE, true)
+
+            // TracingLocalData
+            putLong(EncryptedPreferencesMigration.TracingLocalData.PKEY_POOLING_TEST_RESULT_STARTED, 10101010L)
+            putBoolean(EncryptedPreferencesMigration.TracingLocalData.PKEY_TEST_RESULT_NOTIFICATION, true)
+            putBoolean(EncryptedPreferencesMigration.TracingLocalData.PKEY_HAS_RISK_STATUS_LOWERED, true)
+            putLong(EncryptedPreferencesMigration.TracingLocalData.PKEY_TRACING_ACTIVATION_TIME, 10101010L)
+
+            // SubmissionLocalData
+            putString(EncryptedPreferencesMigration.SubmissionLocalData.PKEY_REGISTRATION_TOKEN, "super_secret_token")
+            putLong(EncryptedPreferencesMigration.SubmissionLocalData.PKEY_INITIAL_RESULT_RECEIVED_TIME, 10101010L)
+            putLong(EncryptedPreferencesMigration.SubmissionLocalData.PKEY_DEVICE_PARING_SUCCESSFUL_TIME, 10101010L)
+            putInt(EncryptedPreferencesMigration.SubmissionLocalData.PKEY_NUMBER_SUCCESSFUL_SUBMISSIONS, 1)
+            putBoolean(EncryptedPreferencesMigration.SubmissionLocalData.PKEY_IS_ALLOWED_TO_SUBMIT, true)
+        }
+    }
+
+    @Test
+    fun `is migration successful`() {
+        every { context.getDatabasePath("coronawarnapp-db") } returns dbFile
+        every { encryptedPreferencesHelper.clean() } just Runs
+
+        val oldPreferences = createOldPreferences()
+        every { encryptedPreferencesHelper.instance } returns oldPreferences
+
+        // SettingsLocalData
+        every { cwaSettings.wasInteroperabilityShownAtLeastOnce = true } just Runs
+        val mockRiskPreference = mockFlowPreference(true)
+        every { cwaSettings.isNotificationsRiskEnabled } returns mockRiskPreference
+        val mockTestPreference = mockFlowPreference(true)
+        every { cwaSettings.isNotificationsTestEnabled } returns mockTestPreference
+        every { cwaSettings.numberOfRemainingSharePositiveTestResultReminders = Int.MAX_VALUE } just Runs
+
+        // OnboardingLocalData
+        every { onboardingSettings.onboardingCompletedTimestamp = Instant.ofEpochMilli(10101010L) } just Runs
+        every { onboardingSettings.isBackgroundCheckDone = true } just Runs
+
+        // TracingLocalData
+        every { tracingSettings.initialPollingForTestResultTimeStamp = 10101010L } just Runs
+        every { tracingSettings.isTestResultAvailableNotificationSent = true } just Runs
+        val mockNotificationPreference = mockFlowPreference(false)
+        every { tracingSettings.isUserToBeNotifiedOfLoweredRiskLevel } returns mockNotificationPreference
+        every { tracingSettings.isConsentGiven = true } just Runs
+
+        // SubmissionLocalData
+        val mockRegtokenPreference = mockFlowPreference<String?>(null)
+        every { submissionSettings.registrationToken } returns mockRegtokenPreference
+        every { submissionSettings.initialTestResultReceivedAt = Instant.ofEpochMilli(10101010L) } just Runs
+        every { submissionSettings.devicePairingSuccessfulAt = Instant.ofEpochMilli(10101010L) } just Runs
+        every { submissionSettings.isSubmissionSuccessful = true } just Runs
+        every { submissionSettings.isAllowedToSubmitKeys = true } just Runs
+
+        val migrationInstance = createInstance()
+
+        migrationInstance.doMigration()
+
+        // SettingsLocalData
+        mockRiskPreference.value shouldBe false
+        mockTestPreference.value shouldBe false
+
+        // TracingLocalData
+        mockNotificationPreference.value shouldBe true
+
+        // SubmissionLocalData
+        mockRegtokenPreference.value shouldBe "super_secret_token"
+    }
+
+    @Test
+    fun `error during migration will be caught`() {
+        every { context.getDatabasePath("coronawarnapp-db") } returns dbFile
+
+        val mockPrefs = mockk<SharedPreferences>()
+        every {
+            mockPrefs.getBoolean(
+                EncryptedPreferencesMigration.SettingsLocalData.PREFERENCE_INTEROPERABILITY_WAS_USED,
+                false
+            )
+        } throws Exception("No one expects the spanish inquisition")
+
+        every { encryptedPreferencesHelper.instance } returns mockPrefs
+        every { encryptedPreferencesHelper.clean() } just Runs
+
+        every { encryptedErrorResetTool.isResetNoticeToBeShown = true } just Runs
+
+        shouldNotThrowAny {
+            val instance = createInstance()
+            instance.doMigration()
+        }
+    }
+}