Merge pull request #91 from kirmanak/simplify-tests

Create testing module to simplify tests
This commit is contained in:
Kirill Kamakin
2022-11-12 14:13:15 +01:00
committed by GitHub
26 changed files with 139 additions and 182 deletions

View File

@@ -70,6 +70,7 @@ dependencies {
implementation(project(":datastore")) implementation(project(":datastore"))
implementation(project(":datasource")) implementation(project(":datasource"))
implementation(project(":logging")) implementation(project(":logging"))
testImplementation(project(":testing"))
implementation(libs.android.material.material) implementation(libs.android.material.material)

View File

@@ -4,8 +4,7 @@ import com.google.common.truth.Truth.assertThat
import gq.kirmanak.mealient.data.add.AddRecipeDataSource import gq.kirmanak.mealient.data.add.AddRecipeDataSource
import gq.kirmanak.mealient.data.add.AddRecipeRepo import gq.kirmanak.mealient.data.add.AddRecipeRepo
import gq.kirmanak.mealient.datastore.recipe.AddRecipeStorage import gq.kirmanak.mealient.datastore.recipe.AddRecipeStorage
import gq.kirmanak.mealient.logging.Logger import gq.kirmanak.mealient.test.BaseUnitTest
import gq.kirmanak.mealient.test.FakeLogger
import gq.kirmanak.mealient.test.RecipeImplTestData.PORRIDGE_ADD_RECIPE_INFO import gq.kirmanak.mealient.test.RecipeImplTestData.PORRIDGE_ADD_RECIPE_INFO
import gq.kirmanak.mealient.test.RecipeImplTestData.PORRIDGE_RECIPE_DRAFT import gq.kirmanak.mealient.test.RecipeImplTestData.PORRIDGE_RECIPE_DRAFT
import io.mockk.* import io.mockk.*
@@ -17,7 +16,7 @@ import org.junit.Before
import org.junit.Test import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class AddRecipeRepoTest { class AddRecipeRepoTest : BaseUnitTest() {
@MockK(relaxUnitFun = true) @MockK(relaxUnitFun = true)
lateinit var dataSource: AddRecipeDataSource lateinit var dataSource: AddRecipeDataSource
@@ -25,13 +24,11 @@ class AddRecipeRepoTest {
@MockK(relaxUnitFun = true) @MockK(relaxUnitFun = true)
lateinit var storage: AddRecipeStorage lateinit var storage: AddRecipeStorage
private val logger: Logger = FakeLogger()
private lateinit var subject: AddRecipeRepo private lateinit var subject: AddRecipeRepo
@Before @Before
fun setUp() { override fun setUp() {
MockKAnnotations.init(this) super.setUp()
subject = AddRecipeRepoImpl(dataSource, storage, logger) subject = AddRecipeRepoImpl(dataSource, storage, logger)
} }

View File

@@ -2,15 +2,13 @@ package gq.kirmanak.mealient.data.analytics
import com.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
import gq.kirmanak.mealient.logging.Logger import gq.kirmanak.mealient.test.BaseUnitTest
import gq.kirmanak.mealient.test.FakeLogger
import io.mockk.MockKAnnotations
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
import io.mockk.verify import io.mockk.verify
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
class AnalyticsImplTest { class AnalyticsImplTest : BaseUnitTest() {
@MockK(relaxUnitFun = true) @MockK(relaxUnitFun = true)
lateinit var firebaseAnalytics: FirebaseAnalytics lateinit var firebaseAnalytics: FirebaseAnalytics
@@ -20,11 +18,9 @@ class AnalyticsImplTest {
lateinit var subject: Analytics lateinit var subject: Analytics
private val logger: Logger = FakeLogger()
@Before @Before
fun setUp() { override fun setUp() {
MockKAnnotations.init(this) super.setUp()
subject = AnalyticsImpl(firebaseAnalytics, firebaseCrashlytics, logger) subject = AnalyticsImpl(firebaseAnalytics, firebaseCrashlytics, logger)
} }

View File

@@ -6,14 +6,13 @@ import gq.kirmanak.mealient.data.auth.AuthRepo
import gq.kirmanak.mealient.data.auth.AuthStorage import gq.kirmanak.mealient.data.auth.AuthStorage
import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo
import gq.kirmanak.mealient.datasource.runCatchingExceptCancel import gq.kirmanak.mealient.datasource.runCatchingExceptCancel
import gq.kirmanak.mealient.logging.Logger
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_AUTH_HEADER import gq.kirmanak.mealient.test.AuthImplTestData.TEST_AUTH_HEADER
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_BASE_URL import gq.kirmanak.mealient.test.AuthImplTestData.TEST_BASE_URL
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_PASSWORD import gq.kirmanak.mealient.test.AuthImplTestData.TEST_PASSWORD
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_SERVER_VERSION_V0 import gq.kirmanak.mealient.test.AuthImplTestData.TEST_SERVER_VERSION_V0
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_TOKEN import gq.kirmanak.mealient.test.AuthImplTestData.TEST_TOKEN
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_USERNAME import gq.kirmanak.mealient.test.AuthImplTestData.TEST_USERNAME
import gq.kirmanak.mealient.test.FakeLogger import gq.kirmanak.mealient.test.BaseUnitTest
import io.mockk.* import io.mockk.*
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -24,7 +23,7 @@ import org.junit.Before
import org.junit.Test import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class AuthRepoImplTest { class AuthRepoImplTest : BaseUnitTest() {
@MockK @MockK
lateinit var dataSource: AuthDataSource lateinit var dataSource: AuthDataSource
@@ -35,13 +34,11 @@ class AuthRepoImplTest {
@MockK(relaxUnitFun = true) @MockK(relaxUnitFun = true)
lateinit var storage: AuthStorage lateinit var storage: AuthStorage
private val logger: Logger = FakeLogger()
lateinit var subject: AuthRepo lateinit var subject: AuthRepo
@Before @Before
fun setUp() { override fun setUp() {
MockKAnnotations.init(this) super.setUp()
subject = AuthRepoImpl(storage, dataSource, logger) subject = AuthRepoImpl(storage, dataSource, logger)
} }

View File

@@ -2,12 +2,10 @@ package gq.kirmanak.mealient.data.baseurl
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import gq.kirmanak.mealient.datasource.NetworkError import gq.kirmanak.mealient.datasource.NetworkError
import gq.kirmanak.mealient.logging.Logger
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_BASE_URL import gq.kirmanak.mealient.test.AuthImplTestData.TEST_BASE_URL
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_VERSION import gq.kirmanak.mealient.test.AuthImplTestData.TEST_VERSION
import gq.kirmanak.mealient.test.FakeLogger import gq.kirmanak.mealient.test.BaseUnitTest
import gq.kirmanak.mealient.test.RecipeImplTestData.VERSION_INFO_V0 import gq.kirmanak.mealient.test.RecipeImplTestData.VERSION_INFO_V0
import io.mockk.MockKAnnotations
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.coVerify import io.mockk.coVerify
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
@@ -17,9 +15,7 @@ import org.junit.Before
import org.junit.Test import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class ServerInfoRepoTest { class ServerInfoRepoTest : BaseUnitTest() {
private val logger: Logger = FakeLogger()
private lateinit var subject: ServerInfoRepo private lateinit var subject: ServerInfoRepo
@@ -30,8 +26,8 @@ class ServerInfoRepoTest {
lateinit var dataSource: VersionDataSource lateinit var dataSource: VersionDataSource
@Before @Before
fun setUp() { override fun setUp() {
MockKAnnotations.init(this) super.setUp()
subject = ServerInfoRepoImpl(storage, dataSource, logger) subject = ServerInfoRepoImpl(storage, dataSource, logger)
} }

View File

@@ -6,7 +6,7 @@ import gq.kirmanak.mealient.data.baseurl.impl.ServerInfoStorageImpl
import gq.kirmanak.mealient.data.storage.PreferencesStorage import gq.kirmanak.mealient.data.storage.PreferencesStorage
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_BASE_URL import gq.kirmanak.mealient.test.AuthImplTestData.TEST_BASE_URL
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_VERSION import gq.kirmanak.mealient.test.AuthImplTestData.TEST_VERSION
import io.mockk.MockKAnnotations import gq.kirmanak.mealient.test.BaseUnitTest
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.coVerify import io.mockk.coVerify
import io.mockk.every import io.mockk.every
@@ -17,7 +17,7 @@ import org.junit.Before
import org.junit.Test import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class ServerInfoStorageTest { class ServerInfoStorageTest : BaseUnitTest() {
@MockK(relaxUnitFun = true) @MockK(relaxUnitFun = true)
lateinit var preferencesStorage: PreferencesStorage lateinit var preferencesStorage: PreferencesStorage
@@ -28,8 +28,8 @@ class ServerInfoStorageTest {
private val serverVersionKey = stringPreferencesKey("serverVersionKey") private val serverVersionKey = stringPreferencesKey("serverVersionKey")
@Before @Before
fun setUp() { override fun setUp() {
MockKAnnotations.init(this) super.setUp()
subject = ServerInfoStorageImpl(preferencesStorage) subject = ServerInfoStorageImpl(preferencesStorage)
every { preferencesStorage.baseUrlKey } returns baseUrlKey every { preferencesStorage.baseUrlKey } returns baseUrlKey
every { preferencesStorage.serverVersionKey } returns serverVersionKey every { preferencesStorage.serverVersionKey } returns serverVersionKey

View File

@@ -6,12 +6,11 @@ import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo
import gq.kirmanak.mealient.datasource.NetworkError import gq.kirmanak.mealient.datasource.NetworkError
import gq.kirmanak.mealient.datasource.v0.MealieDataSourceV0 import gq.kirmanak.mealient.datasource.v0.MealieDataSourceV0
import gq.kirmanak.mealient.datasource.v1.MealieDataSourceV1 import gq.kirmanak.mealient.datasource.v1.MealieDataSourceV1
import gq.kirmanak.mealient.logging.Logger
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_AUTH_HEADER import gq.kirmanak.mealient.test.AuthImplTestData.TEST_AUTH_HEADER
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_BASE_URL import gq.kirmanak.mealient.test.AuthImplTestData.TEST_BASE_URL
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_SERVER_VERSION_V0 import gq.kirmanak.mealient.test.AuthImplTestData.TEST_SERVER_VERSION_V0
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_SERVER_VERSION_V1 import gq.kirmanak.mealient.test.AuthImplTestData.TEST_SERVER_VERSION_V1
import gq.kirmanak.mealient.test.FakeLogger import gq.kirmanak.mealient.test.BaseUnitTest
import gq.kirmanak.mealient.test.RecipeImplTestData.PORRIDGE_ADD_RECIPE_INFO import gq.kirmanak.mealient.test.RecipeImplTestData.PORRIDGE_ADD_RECIPE_INFO
import gq.kirmanak.mealient.test.RecipeImplTestData.PORRIDGE_ADD_RECIPE_REQUEST_V0 import gq.kirmanak.mealient.test.RecipeImplTestData.PORRIDGE_ADD_RECIPE_REQUEST_V0
import gq.kirmanak.mealient.test.RecipeImplTestData.PORRIDGE_CREATE_RECIPE_REQUEST_V1 import gq.kirmanak.mealient.test.RecipeImplTestData.PORRIDGE_CREATE_RECIPE_REQUEST_V1
@@ -32,7 +31,7 @@ import org.junit.Test
import java.io.IOException import java.io.IOException
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class MealieDataSourceWrapperTest { class MealieDataSourceWrapperTest : BaseUnitTest() {
@MockK @MockK
lateinit var serverInfoRepo: ServerInfoRepo lateinit var serverInfoRepo: ServerInfoRepo
@@ -48,11 +47,9 @@ class MealieDataSourceWrapperTest {
lateinit var subject: MealieDataSourceWrapper lateinit var subject: MealieDataSourceWrapper
private val logger: Logger = FakeLogger()
@Before @Before
fun setUp() { override fun setUp() {
MockKAnnotations.init(this) super.setUp()
subject = MealieDataSourceWrapper(serverInfoRepo, authRepo, v0Source, v1Source, logger) subject = MealieDataSourceWrapper(serverInfoRepo, authRepo, v0Source, v1Source, logger)
} }

View File

@@ -2,9 +2,7 @@ package gq.kirmanak.mealient.data.recipes.impl
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo
import gq.kirmanak.mealient.logging.Logger import gq.kirmanak.mealient.test.BaseUnitTest
import gq.kirmanak.mealient.test.FakeLogger
import io.mockk.MockKAnnotations
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -13,18 +11,16 @@ import org.junit.Before
import org.junit.Test import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class RecipeImageUrlProviderImplTest { class RecipeImageUrlProviderImplTest : BaseUnitTest() {
lateinit var subject: RecipeImageUrlProvider lateinit var subject: RecipeImageUrlProvider
@MockK @MockK
lateinit var serverInfoRepo: ServerInfoRepo lateinit var serverInfoRepo: ServerInfoRepo
private val logger: Logger = FakeLogger()
@Before @Before
fun setUp() { override fun setUp() {
MockKAnnotations.init(this) super.setUp()
subject = RecipeImageUrlProviderImpl(serverInfoRepo, logger) subject = RecipeImageUrlProviderImpl(serverInfoRepo, logger)
prepareBaseURL("https://google.com/") prepareBaseURL("https://google.com/")
} }

View File

@@ -6,11 +6,9 @@ import gq.kirmanak.mealient.data.recipes.RecipeRepo
import gq.kirmanak.mealient.data.recipes.db.RecipeStorage import gq.kirmanak.mealient.data.recipes.db.RecipeStorage
import gq.kirmanak.mealient.data.recipes.network.RecipeDataSource import gq.kirmanak.mealient.data.recipes.network.RecipeDataSource
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
import gq.kirmanak.mealient.logging.Logger import gq.kirmanak.mealient.test.BaseUnitTest
import gq.kirmanak.mealient.test.FakeLogger
import gq.kirmanak.mealient.test.RecipeImplTestData.CAKE_FULL_RECIPE_INFO import gq.kirmanak.mealient.test.RecipeImplTestData.CAKE_FULL_RECIPE_INFO
import gq.kirmanak.mealient.test.RecipeImplTestData.FULL_CAKE_INFO_ENTITY import gq.kirmanak.mealient.test.RecipeImplTestData.FULL_CAKE_INFO_ENTITY
import io.mockk.MockKAnnotations
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.coVerify import io.mockk.coVerify
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
@@ -20,7 +18,7 @@ import org.junit.Before
import org.junit.Test import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class RecipeRepoTest { class RecipeRepoTest : BaseUnitTest() {
@MockK(relaxUnitFun = true) @MockK(relaxUnitFun = true)
lateinit var storage: RecipeStorage lateinit var storage: RecipeStorage
@@ -34,13 +32,11 @@ class RecipeRepoTest {
@MockK @MockK
lateinit var pagingSourceFactory: InvalidatingPagingSourceFactory<Int, RecipeSummaryEntity> lateinit var pagingSourceFactory: InvalidatingPagingSourceFactory<Int, RecipeSummaryEntity>
private val logger: Logger = FakeLogger()
lateinit var subject: RecipeRepo lateinit var subject: RecipeRepo
@Before @Before
fun setUp() { override fun setUp() {
MockKAnnotations.init(this) super.setUp()
subject = RecipeRepoImpl(remoteMediator, storage, pagingSourceFactory, dataSource, logger) subject = RecipeRepoImpl(remoteMediator, storage, pagingSourceFactory, dataSource, logger)
} }

View File

@@ -7,10 +7,8 @@ import gq.kirmanak.mealient.data.recipes.db.RecipeStorage
import gq.kirmanak.mealient.data.recipes.network.RecipeDataSource import gq.kirmanak.mealient.data.recipes.network.RecipeDataSource
import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity import gq.kirmanak.mealient.database.recipe.entity.RecipeSummaryEntity
import gq.kirmanak.mealient.datasource.NetworkError.Unauthorized import gq.kirmanak.mealient.datasource.NetworkError.Unauthorized
import gq.kirmanak.mealient.logging.Logger import gq.kirmanak.mealient.test.BaseUnitTest
import gq.kirmanak.mealient.test.FakeLogger
import gq.kirmanak.mealient.test.RecipeImplTestData.TEST_RECIPE_SUMMARIES import gq.kirmanak.mealient.test.RecipeImplTestData.TEST_RECIPE_SUMMARIES
import io.mockk.MockKAnnotations
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.coVerify import io.mockk.coVerify
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
@@ -22,7 +20,8 @@ import org.junit.Test
@ExperimentalCoroutinesApi @ExperimentalCoroutinesApi
@OptIn(ExperimentalPagingApi::class) @OptIn(ExperimentalPagingApi::class)
class RecipesRemoteMediatorTest { class RecipesRemoteMediatorTest : BaseUnitTest() {
private val pagingConfig = PagingConfig( private val pagingConfig = PagingConfig(
pageSize = 2, pageSize = 2,
prefetchDistance = 5, prefetchDistance = 5,
@@ -40,11 +39,9 @@ class RecipesRemoteMediatorTest {
@MockK(relaxUnitFun = true) @MockK(relaxUnitFun = true)
lateinit var pagingSourceFactory: InvalidatingPagingSourceFactory<Int, RecipeSummaryEntity> lateinit var pagingSourceFactory: InvalidatingPagingSourceFactory<Int, RecipeSummaryEntity>
private val logger: Logger = FakeLogger()
@Before @Before
fun setUp() { override fun setUp() {
MockKAnnotations.init(this) super.setUp()
subject = RecipesRemoteMediator(storage, dataSource, pagingSourceFactory, logger) subject = RecipesRemoteMediator(storage, dataSource, pagingSourceFactory, logger)
} }

View File

@@ -1,6 +1,7 @@
package gq.kirmanak.mealient.extensions package gq.kirmanak.mealient.extensions
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import gq.kirmanak.mealient.test.BaseUnitTest
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.toList import kotlinx.coroutines.flow.toList
@@ -8,7 +9,7 @@ import kotlinx.coroutines.test.runTest
import org.junit.Test import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class FlowExtensionsKtTest { class FlowExtensionsKtTest : BaseUnitTest() {
@Test @Test
fun `when flow has an update then valueUpdatesOnly sends updated value`() = runTest { fun `when flow has an update then valueUpdatesOnly sends updated value`() = runTest {

View File

@@ -1,6 +1,7 @@
package gq.kirmanak.mealient.extensions package gq.kirmanak.mealient.extensions
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import gq.kirmanak.mealient.test.BaseUnitTest
import gq.kirmanak.mealient.test.RecipeImplTestData.CAKE_FULL_RECIPE_INFO import gq.kirmanak.mealient.test.RecipeImplTestData.CAKE_FULL_RECIPE_INFO
import gq.kirmanak.mealient.test.RecipeImplTestData.CAKE_RECIPE_ENTITY import gq.kirmanak.mealient.test.RecipeImplTestData.CAKE_RECIPE_ENTITY
import gq.kirmanak.mealient.test.RecipeImplTestData.CAKE_SUGAR_RECIPE_INGREDIENT_ENTITY import gq.kirmanak.mealient.test.RecipeImplTestData.CAKE_SUGAR_RECIPE_INGREDIENT_ENTITY
@@ -32,7 +33,7 @@ import gq.kirmanak.mealient.test.RecipeImplTestData.VERSION_RESPONSE_V0
import gq.kirmanak.mealient.test.RecipeImplTestData.VERSION_RESPONSE_V1 import gq.kirmanak.mealient.test.RecipeImplTestData.VERSION_RESPONSE_V1
import org.junit.Test import org.junit.Test
class ModelMappingsTest { class ModelMappingsTest : BaseUnitTest() {
@Test @Test
fun `when toAddRecipeRequest then fills fields correctly`() { fun `when toAddRecipeRequest then fills fields correctly`() {

View File

@@ -2,49 +2,34 @@ package gq.kirmanak.mealient.ui.add
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import gq.kirmanak.mealient.data.add.AddRecipeRepo import gq.kirmanak.mealient.data.add.AddRecipeRepo
import gq.kirmanak.mealient.logging.Logger import gq.kirmanak.mealient.test.BaseUnitTest
import gq.kirmanak.mealient.test.FakeLogger
import gq.kirmanak.mealient.test.RecipeImplTestData.PORRIDGE_ADD_RECIPE_INFO import gq.kirmanak.mealient.test.RecipeImplTestData.PORRIDGE_ADD_RECIPE_INFO
import io.mockk.MockKAnnotations
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.coVerify import io.mockk.coVerify
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import kotlinx.coroutines.withTimeoutOrNull import kotlinx.coroutines.withTimeoutOrNull
import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class AddRecipeViewModelTest { class AddRecipeViewModelTest : BaseUnitTest() {
@MockK(relaxUnitFun = true) @MockK(relaxUnitFun = true)
lateinit var addRecipeRepo: AddRecipeRepo lateinit var addRecipeRepo: AddRecipeRepo
private val logger: Logger = FakeLogger()
lateinit var subject: AddRecipeViewModel lateinit var subject: AddRecipeViewModel
@Before @Before
fun setUp() { override fun setUp() {
MockKAnnotations.init(this) super.setUp()
Dispatchers.setMain(UnconfinedTestDispatcher())
subject = AddRecipeViewModel(addRecipeRepo, logger) subject = AddRecipeViewModel(addRecipeRepo, logger)
} }
@After
fun tearDown() {
Dispatchers.resetMain()
}
@Test @Test
fun `when saveRecipe fails then addRecipeResult is false`() = runTest { fun `when saveRecipe fails then addRecipeResult is false`() = runTest {
coEvery { addRecipeRepo.saveRecipe() } throws IllegalStateException() coEvery { addRecipeRepo.saveRecipe() } throws IllegalStateException()

View File

@@ -1,32 +1,26 @@
package gq.kirmanak.mealient.ui.baseurl package gq.kirmanak.mealient.ui.baseurl
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import gq.kirmanak.mealient.data.auth.AuthRepo import gq.kirmanak.mealient.data.auth.AuthRepo
import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo
import gq.kirmanak.mealient.data.baseurl.VersionDataSource import gq.kirmanak.mealient.data.baseurl.VersionDataSource
import gq.kirmanak.mealient.data.baseurl.VersionInfo import gq.kirmanak.mealient.data.baseurl.VersionInfo
import gq.kirmanak.mealient.data.recipes.RecipeRepo import gq.kirmanak.mealient.data.recipes.RecipeRepo
import gq.kirmanak.mealient.logging.Logger
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_BASE_URL import gq.kirmanak.mealient.test.AuthImplTestData.TEST_BASE_URL
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_VERSION import gq.kirmanak.mealient.test.AuthImplTestData.TEST_VERSION
import gq.kirmanak.mealient.test.FakeLogger import gq.kirmanak.mealient.test.BaseUnitTest
import gq.kirmanak.mealient.ui.OperationUiState import gq.kirmanak.mealient.ui.OperationUiState
import io.mockk.MockKAnnotations
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.coVerify import io.mockk.coVerify
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.* import kotlinx.coroutines.test.*
import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Rule
import org.junit.Test import org.junit.Test
import java.io.IOException import java.io.IOException
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class BaseURLViewModelTest { class BaseURLViewModelTest : BaseUnitTest() {
@MockK(relaxUnitFun = true) @MockK(relaxUnitFun = true)
lateinit var serverInfoRepo: ServerInfoRepo lateinit var serverInfoRepo: ServerInfoRepo
@@ -40,17 +34,11 @@ class BaseURLViewModelTest {
@MockK @MockK
lateinit var versionDataSource: VersionDataSource lateinit var versionDataSource: VersionDataSource
@get:Rule
val instantExecutorRule = InstantTaskExecutorRule()
private val logger: Logger = FakeLogger()
lateinit var subject: BaseURLViewModel lateinit var subject: BaseURLViewModel
@Before @Before
fun setUp() { override fun setUp() {
MockKAnnotations.init(this) super.setUp()
Dispatchers.setMain(UnconfinedTestDispatcher())
subject = BaseURLViewModel( subject = BaseURLViewModel(
serverInfoRepo = serverInfoRepo, serverInfoRepo = serverInfoRepo,
authRepo = authRepo, authRepo = authRepo,
@@ -60,11 +48,6 @@ class BaseURLViewModelTest {
) )
} }
@After
fun tearDown() {
Dispatchers.resetMain()
}
@Test @Test
fun `when saveBaseURL expect no version checks given that current URL matches new`() = runTest { fun `when saveBaseURL expect no version checks given that current URL matches new`() = runTest {
setupSaveBaseUrlWithOldUrl() setupSaveBaseUrlWithOldUrl()

View File

@@ -2,9 +2,7 @@ package gq.kirmanak.mealient.ui.disclaimer
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import gq.kirmanak.mealient.data.disclaimer.DisclaimerStorage import gq.kirmanak.mealient.data.disclaimer.DisclaimerStorage
import gq.kirmanak.mealient.logging.Logger import gq.kirmanak.mealient.test.BaseUnitTest
import gq.kirmanak.mealient.test.FakeLogger
import io.mockk.MockKAnnotations
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.take import kotlinx.coroutines.flow.take
@@ -15,17 +13,16 @@ import org.junit.Test
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class DisclaimerViewModelTest { class DisclaimerViewModelTest : BaseUnitTest() {
@MockK(relaxUnitFun = true) @MockK(relaxUnitFun = true)
lateinit var storage: DisclaimerStorage lateinit var storage: DisclaimerStorage
private val logger: Logger = FakeLogger()
lateinit var subject: DisclaimerViewModel lateinit var subject: DisclaimerViewModel
@Before @Before
fun setUp() { override fun setUp() {
MockKAnnotations.init(this) super.setUp()
subject = DisclaimerViewModel(storage, logger) subject = DisclaimerViewModel(storage, logger)
} }

View File

@@ -1,32 +1,22 @@
package gq.kirmanak.mealient.ui.recipes package gq.kirmanak.mealient.ui.recipes
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.asFlow import androidx.lifecycle.asFlow
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import gq.kirmanak.mealient.data.auth.AuthRepo import gq.kirmanak.mealient.data.auth.AuthRepo
import gq.kirmanak.mealient.data.recipes.RecipeRepo import gq.kirmanak.mealient.data.recipes.RecipeRepo
import gq.kirmanak.mealient.logging.Logger import gq.kirmanak.mealient.test.BaseUnitTest
import gq.kirmanak.mealient.test.FakeLogger
import io.mockk.MockKAnnotations
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.coVerify import io.mockk.coVerify
import io.mockk.every import io.mockk.every
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class RecipeViewModelTest { class RecipeViewModelTest : BaseUnitTest() {
@MockK @MockK
lateinit var authRepo: AuthRepo lateinit var authRepo: AuthRepo
@@ -34,22 +24,6 @@ class RecipeViewModelTest {
@MockK(relaxed = true) @MockK(relaxed = true)
lateinit var recipeRepo: RecipeRepo lateinit var recipeRepo: RecipeRepo
private val logger: Logger = FakeLogger()
@get:Rule
val instantExecutorRule = InstantTaskExecutorRule()
@Before
fun setUp() {
MockKAnnotations.init(this)
Dispatchers.setMain(UnconfinedTestDispatcher())
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
@Test @Test
fun `when authRepo isAuthorized changes to true expect isAuthorized update`() { fun `when authRepo isAuthorized changes to true expect isAuthorized update`() {
every { authRepo.isAuthorizedFlow } returns flowOf(false, true) every { authRepo.isAuthorizedFlow } returns flowOf(false, true)

View File

@@ -1,51 +1,24 @@
package gq.kirmanak.mealient.ui.recipes.info package gq.kirmanak.mealient.ui.recipes.info
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.asFlow import androidx.lifecycle.asFlow
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import gq.kirmanak.mealient.data.recipes.RecipeRepo import gq.kirmanak.mealient.data.recipes.RecipeRepo
import gq.kirmanak.mealient.database.recipe.entity.RecipeIngredientEntity import gq.kirmanak.mealient.database.recipe.entity.RecipeIngredientEntity
import gq.kirmanak.mealient.logging.Logger import gq.kirmanak.mealient.test.BaseUnitTest
import gq.kirmanak.mealient.test.FakeLogger
import gq.kirmanak.mealient.test.RecipeImplTestData.FULL_CAKE_INFO_ENTITY import gq.kirmanak.mealient.test.RecipeImplTestData.FULL_CAKE_INFO_ENTITY
import io.mockk.MockKAnnotations
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class RecipeInfoViewModelTest { class RecipeInfoViewModelTest : BaseUnitTest() {
@get:Rule
val instantExecutorRule = InstantTaskExecutorRule()
private val logger: Logger = FakeLogger()
@MockK @MockK
lateinit var recipeRepo: RecipeRepo lateinit var recipeRepo: RecipeRepo
@Before
fun setUp() {
MockKAnnotations.init(this)
Dispatchers.setMain(UnconfinedTestDispatcher())
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
@Test @Test
fun `when recipe isn't found then UI state is empty`() = runTest { fun `when recipe isn't found then UI state is empty`() = runTest {
coEvery { recipeRepo.loadRecipeInfo(eq(RECIPE_ID)) } returns null coEvery { recipeRepo.loadRecipeInfo(eq(RECIPE_ID)) } returns null

View File

@@ -14,6 +14,7 @@ android {
dependencies { dependencies {
implementation(project(":logging")) implementation(project(":logging"))
testImplementation(project(":testing"))
implementation(libs.google.dagger.hiltAndroid) implementation(libs.google.dagger.hiltAndroid)
kapt(libs.google.dagger.hiltCompiler) kapt(libs.google.dagger.hiltCompiler)

View File

@@ -5,9 +5,7 @@ import gq.kirmanak.mealient.datasource.v0.MealieDataSourceV0Impl
import gq.kirmanak.mealient.datasource.v0.MealieServiceV0 import gq.kirmanak.mealient.datasource.v0.MealieServiceV0
import gq.kirmanak.mealient.datasource.v0.models.GetTokenResponseV0 import gq.kirmanak.mealient.datasource.v0.models.GetTokenResponseV0
import gq.kirmanak.mealient.datasource.v0.models.VersionResponseV0 import gq.kirmanak.mealient.datasource.v0.models.VersionResponseV0
import gq.kirmanak.mealient.logging.Logger import gq.kirmanak.mealient.test.BaseUnitTest
import gq.kirmanak.mealient.test.toJsonResponseBody
import io.mockk.MockKAnnotations
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -22,19 +20,16 @@ import java.io.IOException
import java.net.ConnectException import java.net.ConnectException
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class MealieDataSourceV0ImplTest { class MealieDataSourceV0ImplTest : BaseUnitTest() {
@MockK @MockK
lateinit var service: MealieServiceV0 lateinit var service: MealieServiceV0
@MockK(relaxUnitFun = true)
lateinit var logger: Logger
lateinit var subject: MealieDataSourceV0Impl lateinit var subject: MealieDataSourceV0Impl
@Before @Before
fun setUp() { override fun setUp() {
MockKAnnotations.init(this) super.setUp()
val networkRequestWrapper: NetworkRequestWrapper = NetworkRequestWrapperImpl(logger) val networkRequestWrapper: NetworkRequestWrapper = NetworkRequestWrapperImpl(logger)
subject = MealieDataSourceV0Impl(networkRequestWrapper, service, Json) subject = MealieDataSourceV0Impl(networkRequestWrapper, service, Json)
} }

View File

@@ -1,4 +1,4 @@
package gq.kirmanak.mealient.test package gq.kirmanak.mealient.datasource
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.ResponseBody.Companion.toResponseBody import okhttp3.ResponseBody.Companion.toResponseBody

View File

@@ -25,3 +25,4 @@ include(":database")
include(":datastore") include(":datastore")
include(":logging") include(":logging")
include(":datasource") include(":datasource")
include(":testing")

1
testing/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

39
testing/build.gradle.kts Normal file
View File

@@ -0,0 +1,39 @@
plugins {
id("gq.kirmanak.mealient.library")
id("kotlin-kapt")
id("dagger.hilt.android.plugin")
}
android {
namespace = "gq.kirmanak.mealient.test"
lint {
abortOnError = false
quiet = true
checkReleaseBuilds = false
}
}
dependencies {
implementation(project(":logging"))
implementation(libs.google.dagger.hiltAndroid)
kapt(libs.google.dagger.hiltCompiler)
kapt(libs.google.dagger.hiltAndroidCompiler)
implementation(libs.google.dagger.hiltAndroidTesting)
implementation(libs.jetbrains.kotlinx.coroutinesAndroid)
implementation(libs.jetbrains.kotlinx.coroutinesTest)
implementation(libs.androidx.test.junit)
implementation(libs.androidx.coreTesting)
implementation(libs.google.truth)
implementation(libs.io.mockk)
implementation(libs.robolectric)
}
kapt {
correctErrorTypes = true
}

View File

@@ -0,0 +1,33 @@
package gq.kirmanak.mealient.test
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import gq.kirmanak.mealient.logging.Logger
import io.mockk.MockKAnnotations
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
import org.junit.Rule
@OptIn(ExperimentalCoroutinesApi::class)
open class BaseUnitTest {
@get:Rule
val instantExecutorRule = InstantTaskExecutorRule()
protected val logger: Logger = FakeLogger()
@Before
open fun setUp() {
MockKAnnotations.init(this)
Dispatchers.setMain(UnconfinedTestDispatcher())
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
}