From 4d5bd9eca498aefd625615903860001169bbf45d Mon Sep 17 00:00:00 2001 From: Mugurell Date: Thu, 7 Oct 2021 14:06:19 +0300 Subject: [PATCH] For #21733 - Replace mock of an interface with mock of a fake. --- .../fenix/home/PocketUpdatesMiddlewareTest.kt | 48 +++++++++++++++---- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/app/src/test/java/org/mozilla/fenix/home/PocketUpdatesMiddlewareTest.kt b/app/src/test/java/org/mozilla/fenix/home/PocketUpdatesMiddlewareTest.kt index 1314e28ca..b91bfa14d 100644 --- a/app/src/test/java/org/mozilla/fenix/home/PocketUpdatesMiddlewareTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/PocketUpdatesMiddlewareTest.kt @@ -11,6 +11,8 @@ import io.mockk.mockk import io.mockk.spyk import io.mockk.verify import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.TestCoroutineScope import mozilla.components.service.pocket.PocketRecommendedStory @@ -59,6 +61,7 @@ class PocketUpdatesMiddlewareTest { } @Test + @Suppress("UNCHECKED_CAST") fun `WHEN PocketStoriesCategoriesChange is dispatched THEN intercept and dispatch PocketStoriesCategoriesSelectionsChange`() { val persistedSelectedCategory: SelectedPocketStoriesCategory = mockk { every { name } returns "testCategory" @@ -67,9 +70,10 @@ class PocketUpdatesMiddlewareTest { val persistedSelectedCategories: SelectedPocketStoriesCategories = mockk { every { valuesList } returns mutableListOf(persistedSelectedCategory) } - val dataStore: DataStore = mockk { - every { data } returns flowOf(persistedSelectedCategories) - } + val dataStore: DataStore = + mockk>(relaxed = true) { + every { data } returns flowOf(persistedSelectedCategories) + } as DataStore val currentCategories = listOf(mockk()) val pocketMiddleware = PocketUpdatesMiddleware(TestCoroutineScope(), mockk(), dataStore) val homeStore = spyk( @@ -96,10 +100,13 @@ class PocketUpdatesMiddlewareTest { } @Test + @Suppress("UNCHECKED_CAST") fun `WHEN SelectPocketStoriesCategory is dispatched THEN persist details in DataStore`() { val categ1 = PocketRecommendedStoriesCategory("categ1") val categ2 = PocketRecommendedStoriesCategory("categ2") - val dataStore: DataStore = mockk(relaxed = true) + val dataStore: DataStore = + mockk>(relaxed = true) as + DataStore val pocketMiddleware = PocketUpdatesMiddleware(TestCoroutineScope(), mockk(), dataStore) val homeStore = spyk( HomeFragmentStore( @@ -117,10 +124,13 @@ class PocketUpdatesMiddlewareTest { } @Test + @Suppress("UNCHECKED_CAST") fun `WHEN DeselectPocketStoriesCategory is dispatched THEN persist details in DataStore`() { val categ1 = PocketRecommendedStoriesCategory("categ1") val categ2 = PocketRecommendedStoriesCategory("categ2") - val dataStore: DataStore = mockk(relaxed = true) + val dataStore: DataStore = + mockk>(relaxed = true) as + DataStore val pocketMiddleware = PocketUpdatesMiddleware(TestCoroutineScope(), mockk(), dataStore) val homeStore = spyk( HomeFragmentStore( @@ -138,8 +148,11 @@ class PocketUpdatesMiddlewareTest { } @Test + @Suppress("UNCHECKED_CAST") fun `WHEN persistCategories is called THEN update dataStore`() { - val dataStore: DataStore = mockk(relaxed = true) + val dataStore: DataStore = + mockk>(relaxed = true) as + DataStore persistSelectedCategories(TestCoroutineScope(), listOf(mockk(relaxed = true)), dataStore) @@ -148,6 +161,7 @@ class PocketUpdatesMiddlewareTest { } @Test + @Suppress("UNCHECKED_CAST") fun `WHEN restoreSelectedCategories is called THEN dispatch PocketStoriesCategoriesSelectionsChange with data read from the persistence layer`() { val persistedSelectedCategory: SelectedPocketStoriesCategory = mockk { every { name } returns "testCategory" @@ -156,9 +170,10 @@ class PocketUpdatesMiddlewareTest { val persistedSelectedCategories: SelectedPocketStoriesCategories = mockk { every { valuesList } returns mutableListOf(persistedSelectedCategory) } - val dataStore: DataStore = mockk { - every { data } returns flowOf(persistedSelectedCategories) - } + val dataStore: DataStore = + mockk>(relaxed = true) { + every { data } returns flowOf(persistedSelectedCategories) + } as DataStore val currentCategories = listOf(mockk()) val homeStore = spyk( HomeFragmentStore(HomeFragmentState()) @@ -183,3 +198,18 @@ class PocketUpdatesMiddlewareTest { } } } + +/** + * Incomplete fake of a [DataStore]. + * Respects the [DataStore] contract with basic method implementations but needs to have mocked behavior + * for more complex interactions. + * Can be used as a replacement for mocks of the [DataStore] interface which might fail intermittently. + */ +private class FakeDataStore : DataStore { + override val data: Flow + get() = flow { } + + override suspend fun updateData(transform: suspend (t: T?) -> T?): T? { + return transform(null) + } +}