From 127153cac788b8f9105a2bf36a175f967d873a31 Mon Sep 17 00:00:00 2001 From: Kirill Kamakin Date: Tue, 13 Dec 2022 21:32:39 +0100 Subject: [PATCH] Update unit tests --- .../recipes/impl/RecipesRemoteMediator.kt | 2 +- .../mealient/di/ArchitectureModule.kt | 6 ------ .../data/recipes/db/RecipeStorageImplTest.kt | 20 +++++++++---------- .../impl/RecipePagingSourceFactoryImplTest.kt | 9 ++++----- .../recipes/impl/RecipesRemoteMediatorTest.kt | 16 ++++++++++----- .../mealient/extensions/ModelMappingsTest.kt | 2 +- .../mealient/test/RecipeImplTestData.kt | 2 ++ .../configuration/AppDispatchers.kt | 5 ++--- .../configuration/AppDispatchersImpl.kt | 2 +- .../configuration/ArchitectureModule.kt | 16 +++++++++++++++ testing/build.gradle.kts | 1 + .../gq/kirmanak/mealient/test/BaseUnitTest.kt | 11 ++++++++++ 12 files changed, 59 insertions(+), 33 deletions(-) rename {app/src/main/java/gq/kirmanak/mealient/data => architecture/src/main/kotlin/gq/kirmanak/mealient/architecture}/configuration/AppDispatchers.kt (57%) rename {app/src/main/java/gq/kirmanak/mealient/data => architecture/src/main/kotlin/gq/kirmanak/mealient/architecture}/configuration/AppDispatchersImpl.kt (86%) create mode 100644 architecture/src/main/kotlin/gq/kirmanak/mealient/architecture/configuration/ArchitectureModule.kt diff --git a/app/src/main/java/gq/kirmanak/mealient/data/recipes/impl/RecipesRemoteMediator.kt b/app/src/main/java/gq/kirmanak/mealient/data/recipes/impl/RecipesRemoteMediator.kt index 77dcbef..cdfe112 100644 --- a/app/src/main/java/gq/kirmanak/mealient/data/recipes/impl/RecipesRemoteMediator.kt +++ b/app/src/main/java/gq/kirmanak/mealient/data/recipes/impl/RecipesRemoteMediator.kt @@ -4,7 +4,7 @@ import androidx.annotation.VisibleForTesting import androidx.paging.* import androidx.paging.LoadType.PREPEND import androidx.paging.LoadType.REFRESH -import gq.kirmanak.mealient.data.configuration.AppDispatchers +import gq.kirmanak.mealient.architecture.configuration.AppDispatchers import gq.kirmanak.mealient.data.recipes.db.RecipeStorage import gq.kirmanak.mealient.data.recipes.network.RecipeDataSource import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity diff --git a/app/src/main/java/gq/kirmanak/mealient/di/ArchitectureModule.kt b/app/src/main/java/gq/kirmanak/mealient/di/ArchitectureModule.kt index 11e2378..c322301 100644 --- a/app/src/main/java/gq/kirmanak/mealient/di/ArchitectureModule.kt +++ b/app/src/main/java/gq/kirmanak/mealient/di/ArchitectureModule.kt @@ -5,8 +5,6 @@ import dagger.Module import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import gq.kirmanak.mealient.architecture.configuration.BuildConfiguration -import gq.kirmanak.mealient.data.configuration.AppDispatchers -import gq.kirmanak.mealient.data.configuration.AppDispatchersImpl import gq.kirmanak.mealient.data.configuration.BuildConfigurationImpl import javax.inject.Singleton @@ -17,8 +15,4 @@ interface ArchitectureModule { @Binds @Singleton fun bindBuildConfiguration(buildConfigurationImpl: BuildConfigurationImpl): BuildConfiguration - - @Binds - @Singleton - fun bindAppDispatchers(appDispatchersImpl: AppDispatchersImpl): AppDispatchers } \ No newline at end of file diff --git a/app/src/test/java/gq/kirmanak/mealient/data/recipes/db/RecipeStorageImplTest.kt b/app/src/test/java/gq/kirmanak/mealient/data/recipes/db/RecipeStorageImplTest.kt index 0d3db50..6cfb6f0 100644 --- a/app/src/test/java/gq/kirmanak/mealient/data/recipes/db/RecipeStorageImplTest.kt +++ b/app/src/test/java/gq/kirmanak/mealient/data/recipes/db/RecipeStorageImplTest.kt @@ -14,9 +14,7 @@ import gq.kirmanak.mealient.test.RecipeImplTestData.MIX_CAKE_RECIPE_INSTRUCTION_ import gq.kirmanak.mealient.test.RecipeImplTestData.MIX_INSTRUCTION import gq.kirmanak.mealient.test.RecipeImplTestData.PORRIDGE_FULL_RECIPE_INFO import gq.kirmanak.mealient.test.RecipeImplTestData.PORRIDGE_RECIPE_SUMMARY_ENTITY -import gq.kirmanak.mealient.test.RecipeImplTestData.RECIPE_SUMMARY_CAKE -import gq.kirmanak.mealient.test.RecipeImplTestData.RECIPE_SUMMARY_PORRIDGE_V0 -import gq.kirmanak.mealient.test.RecipeImplTestData.TEST_RECIPE_SUMMARIES +import gq.kirmanak.mealient.test.RecipeImplTestData.TEST_RECIPE_SUMMARY_ENTITIES import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.junit.Test @@ -34,7 +32,7 @@ class RecipeStorageImplTest : HiltRobolectricTest() { @Test fun `when saveRecipes then saves recipes`() = runTest { - subject.saveRecipes(TEST_RECIPE_SUMMARIES) + subject.saveRecipes(TEST_RECIPE_SUMMARY_ENTITIES) val actualTags = appDb.recipeDao().queryAllRecipes() assertThat(actualTags).containsExactly( CAKE_RECIPE_SUMMARY_ENTITY, @@ -44,15 +42,15 @@ class RecipeStorageImplTest : HiltRobolectricTest() { @Test fun `when refreshAll then old recipes aren't preserved`() = runTest { - subject.saveRecipes(TEST_RECIPE_SUMMARIES) - subject.refreshAll(listOf(RECIPE_SUMMARY_CAKE)) + subject.saveRecipes(TEST_RECIPE_SUMMARY_ENTITIES) + subject.refreshAll(listOf(CAKE_RECIPE_SUMMARY_ENTITY)) val actual = appDb.recipeDao().queryAllRecipes() assertThat(actual).containsExactly(CAKE_RECIPE_SUMMARY_ENTITY) } @Test fun `when clearAllLocalData then recipes aren't preserved`() = runTest { - subject.saveRecipes(TEST_RECIPE_SUMMARIES) + subject.saveRecipes(TEST_RECIPE_SUMMARY_ENTITIES) subject.clearAllLocalData() val actual = appDb.recipeDao().queryAllRecipes() assertThat(actual).isEmpty() @@ -60,7 +58,7 @@ class RecipeStorageImplTest : HiltRobolectricTest() { @Test fun `when saveRecipeInfo then saves recipe info`() = runTest { - subject.saveRecipes(listOf(RECIPE_SUMMARY_CAKE)) + subject.saveRecipes(listOf(CAKE_RECIPE_SUMMARY_ENTITY)) subject.saveRecipeInfo(CAKE_FULL_RECIPE_INFO) val actual = appDb.recipeDao().queryFullRecipeInfo("1") assertThat(actual).isEqualTo(FULL_CAKE_INFO_ENTITY) @@ -68,7 +66,7 @@ class RecipeStorageImplTest : HiltRobolectricTest() { @Test fun `when saveRecipeInfo with two then saves second`() = runTest { - subject.saveRecipes(listOf(RECIPE_SUMMARY_CAKE, RECIPE_SUMMARY_PORRIDGE_V0)) + subject.saveRecipes(TEST_RECIPE_SUMMARY_ENTITIES) subject.saveRecipeInfo(CAKE_FULL_RECIPE_INFO) subject.saveRecipeInfo(PORRIDGE_FULL_RECIPE_INFO) val actual = appDb.recipeDao().queryFullRecipeInfo("2") @@ -77,7 +75,7 @@ class RecipeStorageImplTest : HiltRobolectricTest() { @Test fun `when saveRecipeInfo secondly then overwrites ingredients`() = runTest { - subject.saveRecipes(listOf(RECIPE_SUMMARY_CAKE)) + subject.saveRecipes(listOf(CAKE_RECIPE_SUMMARY_ENTITY)) subject.saveRecipeInfo(CAKE_FULL_RECIPE_INFO) val newRecipe = CAKE_FULL_RECIPE_INFO.copy(recipeIngredients = listOf(BREAD_INGREDIENT)) subject.saveRecipeInfo(newRecipe) @@ -88,7 +86,7 @@ class RecipeStorageImplTest : HiltRobolectricTest() { @Test fun `when saveRecipeInfo secondly then overwrites instructions`() = runTest { - subject.saveRecipes(listOf(RECIPE_SUMMARY_CAKE)) + subject.saveRecipes(listOf(CAKE_RECIPE_SUMMARY_ENTITY)) subject.saveRecipeInfo(CAKE_FULL_RECIPE_INFO) val newRecipe = CAKE_FULL_RECIPE_INFO.copy(recipeInstructions = listOf(MIX_INSTRUCTION)) subject.saveRecipeInfo(newRecipe) diff --git a/app/src/test/java/gq/kirmanak/mealient/data/recipes/impl/RecipePagingSourceFactoryImplTest.kt b/app/src/test/java/gq/kirmanak/mealient/data/recipes/impl/RecipePagingSourceFactoryImplTest.kt index d9ec3b9..e5374aa 100644 --- a/app/src/test/java/gq/kirmanak/mealient/data/recipes/impl/RecipePagingSourceFactoryImplTest.kt +++ b/app/src/test/java/gq/kirmanak/mealient/data/recipes/impl/RecipePagingSourceFactoryImplTest.kt @@ -8,7 +8,6 @@ import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity import gq.kirmanak.mealient.test.HiltRobolectricTest import gq.kirmanak.mealient.test.RecipeImplTestData.CAKE_RECIPE_SUMMARY_ENTITY import gq.kirmanak.mealient.test.RecipeImplTestData.PORRIDGE_RECIPE_SUMMARY_ENTITY -import gq.kirmanak.mealient.test.RecipeImplTestData.TEST_RECIPE_SUMMARIES import gq.kirmanak.mealient.test.RecipeImplTestData.TEST_RECIPE_SUMMARY_ENTITIES import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest @@ -27,28 +26,28 @@ class RecipePagingSourceFactoryImplTest : HiltRobolectricTest() { @Test fun `when query is ca expect cake only is returned`() = runTest { - storage.saveRecipes(TEST_RECIPE_SUMMARIES) + storage.saveRecipes(TEST_RECIPE_SUMMARY_ENTITIES) subject.setQuery("ca") assertThat(queryRecipes()).isEqualTo(listOf(CAKE_RECIPE_SUMMARY_ENTITY)) } @Test fun `when query is po expect porridge only is returned`() = runTest { - storage.saveRecipes(TEST_RECIPE_SUMMARIES) + storage.saveRecipes(TEST_RECIPE_SUMMARY_ENTITIES) subject.setQuery("po") assertThat(queryRecipes()).isEqualTo(listOf(PORRIDGE_RECIPE_SUMMARY_ENTITY)) } @Test fun `when query is e expect cake and porridge are returned`() = runTest { - storage.saveRecipes(TEST_RECIPE_SUMMARIES) + storage.saveRecipes(TEST_RECIPE_SUMMARY_ENTITIES) subject.setQuery("e") assertThat(queryRecipes()).isEqualTo(TEST_RECIPE_SUMMARY_ENTITIES) } @Test fun `when query is null expect cake and porridge are returned`() = runTest { - storage.saveRecipes(TEST_RECIPE_SUMMARIES) + storage.saveRecipes(TEST_RECIPE_SUMMARY_ENTITIES) subject.setQuery(null) assertThat(queryRecipes()).isEqualTo(TEST_RECIPE_SUMMARY_ENTITIES) } diff --git a/app/src/test/java/gq/kirmanak/mealient/data/recipes/impl/RecipesRemoteMediatorTest.kt b/app/src/test/java/gq/kirmanak/mealient/data/recipes/impl/RecipesRemoteMediatorTest.kt index ed693f6..5b13581 100644 --- a/app/src/test/java/gq/kirmanak/mealient/data/recipes/impl/RecipesRemoteMediatorTest.kt +++ b/app/src/test/java/gq/kirmanak/mealient/data/recipes/impl/RecipesRemoteMediatorTest.kt @@ -9,6 +9,7 @@ import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity import gq.kirmanak.mealient.datasource.NetworkError.Unauthorized import gq.kirmanak.mealient.test.BaseUnitTest import gq.kirmanak.mealient.test.RecipeImplTestData.TEST_RECIPE_SUMMARIES +import gq.kirmanak.mealient.test.RecipeImplTestData.TEST_RECIPE_SUMMARY_ENTITIES import io.mockk.coEvery import io.mockk.coVerify import io.mockk.impl.annotations.MockK @@ -42,7 +43,14 @@ class RecipesRemoteMediatorTest : BaseUnitTest() { @Before override fun setUp() { super.setUp() - subject = RecipesRemoteMediator(storage, dataSource, pagingSourceFactory, logger) + subject = RecipesRemoteMediator( + storage = storage, + network = dataSource, + pagingSourceFactory = pagingSourceFactory, + logger = logger, + dispatchers = dispatchers, + ) + coEvery { dataSource.getFavoriteRecipes() } returns emptyList() } @Test @@ -70,7 +78,7 @@ class RecipesRemoteMediatorTest : BaseUnitTest() { fun `when first load with refresh successful then recipes stored`() = runTest { coEvery { dataSource.requestRecipes(eq(0), eq(6)) } returns TEST_RECIPE_SUMMARIES subject.load(REFRESH, pagingState()) - coVerify { storage.refreshAll(eq(TEST_RECIPE_SUMMARIES)) } + coVerify { storage.refreshAll(eq(TEST_RECIPE_SUMMARY_ENTITIES)) } } @Test @@ -132,9 +140,7 @@ class RecipesRemoteMediatorTest : BaseUnitTest() { subject.load(REFRESH, pagingState()) coEvery { dataSource.requestRecipes(any(), any()) } throws Unauthorized(RuntimeException()) subject.load(APPEND, pagingState()) - coVerify { - storage.refreshAll(TEST_RECIPE_SUMMARIES) - } + coVerify { storage.refreshAll(TEST_RECIPE_SUMMARY_ENTITIES) } } private fun pagingState( diff --git a/app/src/test/java/gq/kirmanak/mealient/extensions/ModelMappingsTest.kt b/app/src/test/java/gq/kirmanak/mealient/extensions/ModelMappingsTest.kt index 8b6bd81..578af8b 100644 --- a/app/src/test/java/gq/kirmanak/mealient/extensions/ModelMappingsTest.kt +++ b/app/src/test/java/gq/kirmanak/mealient/extensions/ModelMappingsTest.kt @@ -76,7 +76,7 @@ class ModelMappingsTest : BaseUnitTest() { @Test fun `when summary info to entity expect correct entity`() { - val actual = RECIPE_SUMMARY_PORRIDGE_V0.toRecipeSummaryEntity() + val actual = RECIPE_SUMMARY_PORRIDGE_V0.toRecipeSummaryEntity(isFavorite = false) assertThat(actual).isEqualTo(PORRIDGE_RECIPE_SUMMARY_ENTITY) } diff --git a/app/src/test/java/gq/kirmanak/mealient/test/RecipeImplTestData.kt b/app/src/test/java/gq/kirmanak/mealient/test/RecipeImplTestData.kt index 3409031..a80ff6a 100644 --- a/app/src/test/java/gq/kirmanak/mealient/test/RecipeImplTestData.kt +++ b/app/src/test/java/gq/kirmanak/mealient/test/RecipeImplTestData.kt @@ -80,6 +80,7 @@ object RecipeImplTestData { dateAdded = LocalDate.parse("2021-11-13"), dateUpdated = LocalDateTime.parse("2021-11-13T15:30:13"), imageId = "cake", + isFavorite = false, ) val PORRIDGE_RECIPE_SUMMARY_ENTITY = RecipeSummaryEntity( @@ -90,6 +91,7 @@ object RecipeImplTestData { dateAdded = LocalDate.parse("2021-11-12"), dateUpdated = LocalDateTime.parse("2021-10-13T17:35:23"), imageId = "porridge", + isFavorite = false, ) val TEST_RECIPE_SUMMARY_ENTITIES = diff --git a/app/src/main/java/gq/kirmanak/mealient/data/configuration/AppDispatchers.kt b/architecture/src/main/kotlin/gq/kirmanak/mealient/architecture/configuration/AppDispatchers.kt similarity index 57% rename from app/src/main/java/gq/kirmanak/mealient/data/configuration/AppDispatchers.kt rename to architecture/src/main/kotlin/gq/kirmanak/mealient/architecture/configuration/AppDispatchers.kt index 9b3d91a..81cb800 100644 --- a/app/src/main/java/gq/kirmanak/mealient/data/configuration/AppDispatchers.kt +++ b/architecture/src/main/kotlin/gq/kirmanak/mealient/architecture/configuration/AppDispatchers.kt @@ -1,11 +1,10 @@ -package gq.kirmanak.mealient.data.configuration +package gq.kirmanak.mealient.architecture.configuration import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.MainCoroutineDispatcher interface AppDispatchers { val io: CoroutineDispatcher - val main: MainCoroutineDispatcher + val main: CoroutineDispatcher val default: CoroutineDispatcher val unconfined: CoroutineDispatcher } \ No newline at end of file diff --git a/app/src/main/java/gq/kirmanak/mealient/data/configuration/AppDispatchersImpl.kt b/architecture/src/main/kotlin/gq/kirmanak/mealient/architecture/configuration/AppDispatchersImpl.kt similarity index 86% rename from app/src/main/java/gq/kirmanak/mealient/data/configuration/AppDispatchersImpl.kt rename to architecture/src/main/kotlin/gq/kirmanak/mealient/architecture/configuration/AppDispatchersImpl.kt index e7e249d..69680da 100644 --- a/app/src/main/java/gq/kirmanak/mealient/data/configuration/AppDispatchersImpl.kt +++ b/architecture/src/main/kotlin/gq/kirmanak/mealient/architecture/configuration/AppDispatchersImpl.kt @@ -1,4 +1,4 @@ -package gq.kirmanak.mealient.data.configuration +package gq.kirmanak.mealient.architecture.configuration import kotlinx.coroutines.Dispatchers import javax.inject.Inject diff --git a/architecture/src/main/kotlin/gq/kirmanak/mealient/architecture/configuration/ArchitectureModule.kt b/architecture/src/main/kotlin/gq/kirmanak/mealient/architecture/configuration/ArchitectureModule.kt new file mode 100644 index 0000000..2b445b4 --- /dev/null +++ b/architecture/src/main/kotlin/gq/kirmanak/mealient/architecture/configuration/ArchitectureModule.kt @@ -0,0 +1,16 @@ +package gq.kirmanak.mealient.architecture.configuration + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +interface ArchitectureModule { + + @Binds + @Singleton + fun bindAppDispatchers(appDispatchersImpl: AppDispatchersImpl): AppDispatchers +} \ No newline at end of file diff --git a/testing/build.gradle.kts b/testing/build.gradle.kts index 4129da2..83889f8 100644 --- a/testing/build.gradle.kts +++ b/testing/build.gradle.kts @@ -15,6 +15,7 @@ android { dependencies { implementation(project(":logging")) + implementation(project(":architecture")) implementation(libs.google.dagger.hiltAndroid) kapt(libs.google.dagger.hiltCompiler) diff --git a/testing/src/main/kotlin/gq/kirmanak/mealient/test/BaseUnitTest.kt b/testing/src/main/kotlin/gq/kirmanak/mealient/test/BaseUnitTest.kt index 0526aea..aabb40c 100644 --- a/testing/src/main/kotlin/gq/kirmanak/mealient/test/BaseUnitTest.kt +++ b/testing/src/main/kotlin/gq/kirmanak/mealient/test/BaseUnitTest.kt @@ -1,10 +1,13 @@ package gq.kirmanak.mealient.test import androidx.arch.core.executor.testing.InstantTaskExecutorRule +import gq.kirmanak.mealient.architecture.configuration.AppDispatchers import gq.kirmanak.mealient.logging.Logger import io.mockk.MockKAnnotations +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.setMain @@ -20,10 +23,18 @@ open class BaseUnitTest { protected val logger: Logger = FakeLogger() + lateinit var dispatchers: AppDispatchers + @Before open fun setUp() { MockKAnnotations.init(this) Dispatchers.setMain(UnconfinedTestDispatcher()) + dispatchers = object : AppDispatchers { + override val io: CoroutineDispatcher = StandardTestDispatcher() + override val main: CoroutineDispatcher = StandardTestDispatcher() + override val default: CoroutineDispatcher = StandardTestDispatcher() + override val unconfined: CoroutineDispatcher = StandardTestDispatcher() + } } @After