diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/transaction/RetrieveDiagnosisKeysTransactionTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/transaction/RetrieveDiagnosisKeysTransactionTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ec7798a860acc741c31d6bdd2af422511bc41837
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/transaction/RetrieveDiagnosisKeysTransactionTest.kt
@@ -0,0 +1,82 @@
+package de.rki.coronawarnapp.transaction
+
+import com.google.android.gms.nearby.exposurenotification.ExposureConfiguration
+import de.rki.coronawarnapp.nearby.InternalExposureNotificationClient
+import de.rki.coronawarnapp.service.applicationconfiguration.ApplicationConfigurationService
+import de.rki.coronawarnapp.storage.LocalData
+import io.mockk.Runs
+import io.mockk.coEvery
+import io.mockk.coVerifyOrder
+import io.mockk.every
+import io.mockk.just
+import io.mockk.mockk
+import io.mockk.mockkObject
+import io.mockk.unmockkAll
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import java.io.File
+import java.nio.file.Paths
+import java.util.Date
+
+/**
+ * RetrieveDiagnosisKeysTransaction test.
+ */
+class RetrieveDiagnosisKeysTransactionTest {
+
+    @Before
+    fun setUp() {
+        mockkObject(InternalExposureNotificationClient)
+        mockkObject(ApplicationConfigurationService)
+        mockkObject(RetrieveDiagnosisKeysTransaction)
+        mockkObject(LocalData)
+
+        coEvery { InternalExposureNotificationClient.asyncIsEnabled() } returns true
+        coEvery { InternalExposureNotificationClient.asyncProvideDiagnosisKeys(any(), any(), any()) } returns mockk()
+        coEvery { ApplicationConfigurationService.asyncRetrieveExposureConfiguration() } returns mockk()
+        every { LocalData.googleApiToken(any()) } just Runs
+        every { LocalData.lastTimeDiagnosisKeysFromServerFetch() } returns Date()
+        every { LocalData.lastTimeDiagnosisKeysFromServerFetch(any()) } just Runs
+    }
+
+    @Test
+    fun testTransactionNoFiles() {
+        coEvery { RetrieveDiagnosisKeysTransaction["executeFetchKeyFilesFromServer"](any<Date>()) } returns listOf<File>()
+
+        runBlocking {
+            RetrieveDiagnosisKeysTransaction.start()
+
+            coVerifyOrder {
+                RetrieveDiagnosisKeysTransaction["executeSetup"]()
+                RetrieveDiagnosisKeysTransaction["executeRetrieveRiskScoreParams"]()
+                RetrieveDiagnosisKeysTransaction["executeFetchKeyFilesFromServer"](any<Date>())
+                RetrieveDiagnosisKeysTransaction["executeFetchDateUpdate"](any<Date>())
+            }
+        }
+    }
+
+    @Test
+    fun testTransactionHasFiles() {
+        val file = Paths.get("src", "test", "resources", "keys.bin").toFile()
+
+        coEvery { RetrieveDiagnosisKeysTransaction["executeFetchKeyFilesFromServer"](any<Date>()) } returns listOf(file)
+
+        runBlocking {
+            RetrieveDiagnosisKeysTransaction.start()
+
+            coVerifyOrder {
+                RetrieveDiagnosisKeysTransaction["executeSetup"]()
+                RetrieveDiagnosisKeysTransaction["executeRetrieveRiskScoreParams"]()
+                RetrieveDiagnosisKeysTransaction["executeFetchKeyFilesFromServer"](any<Date>())
+                RetrieveDiagnosisKeysTransaction["executeAPISubmission"](any<String>(), listOf(file), any<ExposureConfiguration>())
+                RetrieveDiagnosisKeysTransaction["executeFetchDateUpdate"](any<Date>())
+            }
+        }
+    }
+
+    @After
+    fun cleanUp() {
+        unmockkAll()
+    }
+}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/transaction/SubmitDiagnosisKeysTransactionTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/transaction/SubmitDiagnosisKeysTransactionTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..dd296b9b7f44d4e934c709f6ea37b937012b6210
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/transaction/SubmitDiagnosisKeysTransactionTest.kt
@@ -0,0 +1,79 @@
+package de.rki.coronawarnapp.transaction
+
+import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey
+import de.rki.coronawarnapp.nearby.InternalExposureNotificationClient
+import de.rki.coronawarnapp.service.diagnosiskey.DiagnosisKeyService
+import de.rki.coronawarnapp.service.submission.SubmissionService
+import de.rki.coronawarnapp.storage.LocalData
+import io.mockk.Runs
+import io.mockk.coEvery
+import io.mockk.coVerifyOrder
+import io.mockk.every
+import io.mockk.just
+import io.mockk.mockkObject
+import io.mockk.slot
+import io.mockk.unmockkAll
+import kotlinx.coroutines.runBlocking
+import org.hamcrest.CoreMatchers.`is`
+import org.hamcrest.MatcherAssert.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+
+class SubmitDiagnosisKeysTransactionTest {
+    private val authString = "authString"
+
+    @Before
+    fun setUp() {
+        mockkObject(LocalData)
+        mockkObject(SubmissionService)
+        mockkObject(InternalExposureNotificationClient)
+        mockkObject(DiagnosisKeyService)
+        every { LocalData.numberOfSuccessfulSubmissions(any()) } just Runs
+        coEvery { SubmissionService.asyncRequestAuthCode(any()) } returns authString
+    }
+
+    @Test
+    fun testTransactionNoKeys() {
+        coEvery { InternalExposureNotificationClient.asyncGetTemporaryExposureKeyHistory() } returns listOf()
+        coEvery { DiagnosisKeyService.asyncSubmitKeys(authString, listOf()) } just Runs
+
+        runBlocking {
+            SubmitDiagnosisKeysTransaction.start("123")
+
+            coVerifyOrder {
+                DiagnosisKeyService.asyncSubmitKeys(authString, listOf())
+                SubmissionService.submissionSuccessful()
+            }
+        }
+    }
+
+    @Test
+    fun testTransactionHasKeys() {
+        val key = TemporaryExposureKey.TemporaryExposureKeyBuilder()
+            .setKeyData(ByteArray(1))
+            .setRollingPeriod(1)
+            .setRollingStartIntervalNumber(1)
+            .setTransmissionRiskLevel(1)
+            .build()
+        val testList = slot<List<KeyExportFormat.TemporaryExposureKey>>()
+        coEvery { InternalExposureNotificationClient.asyncGetTemporaryExposureKeyHistory() } returns listOf(key)
+        coEvery { DiagnosisKeyService.asyncSubmitKeys(authString, capture(testList)) } just Runs
+
+        runBlocking {
+            SubmitDiagnosisKeysTransaction.start("123")
+
+            coVerifyOrder {
+                DiagnosisKeyService.asyncSubmitKeys(authString, any())
+                SubmissionService.submissionSuccessful()
+            }
+            assertThat(testList.isCaptured, `is`(true))
+            assertThat(testList.captured.size, `is`(1))
+        }
+    }
+
+    @After
+    fun cleanUp() {
+        unmockkAll()
+    }
+}
diff --git a/Corona-Warn-App/src/test/resources/keys.bin b/Corona-Warn-App/src/test/resources/keys.bin
new file mode 100644
index 0000000000000000000000000000000000000000..61e9ea4b50e5458bcf8e9f46e6203b7c87b8a21e
Binary files /dev/null and b/Corona-Warn-App/src/test/resources/keys.bin differ