Fix failing tests

This commit is contained in:
Kirill Kamakin
2022-10-29 20:24:32 +02:00
parent a06d710f7a
commit 5f9779d904
11 changed files with 121 additions and 108 deletions

View File

@@ -4,12 +4,13 @@ import com.google.common.truth.Truth.assertThat
import gq.kirmanak.mealient.data.auth.AuthDataSource import gq.kirmanak.mealient.data.auth.AuthDataSource
import gq.kirmanak.mealient.data.auth.AuthRepo 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.ServerInfoStorage 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.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
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 io.mockk.* import io.mockk.*
@@ -28,7 +29,7 @@ class AuthRepoImplTest {
lateinit var dataSource: AuthDataSource lateinit var dataSource: AuthDataSource
@MockK @MockK
lateinit var serverInfoStorage: ServerInfoStorage lateinit var serverInfoRepo: ServerInfoRepo
@MockK(relaxUnitFun = true) @MockK(relaxUnitFun = true)
lateinit var storage: AuthStorage lateinit var storage: AuthStorage
@@ -41,7 +42,7 @@ class AuthRepoImplTest {
@Before @Before
fun setUp() { fun setUp() {
MockKAnnotations.init(this) MockKAnnotations.init(this)
subject = AuthRepoImpl(storage, dataSource, serverInfoStorage, logger) subject = AuthRepoImpl(storage, dataSource, serverInfoRepo, logger)
} }
@Test @Test
@@ -52,14 +53,16 @@ class AuthRepoImplTest {
@Test @Test
fun `when authenticate successfully then saves to storage`() = runTest { fun `when authenticate successfully then saves to storage`() = runTest {
coEvery { serverInfoRepo.getVersion() } returns TEST_SERVER_VERSION
coEvery { coEvery {
dataSource.authenticate( dataSource.authenticate(
eq(TEST_USERNAME), eq(TEST_USERNAME),
eq(TEST_PASSWORD), eq(TEST_PASSWORD),
eq(TEST_BASE_URL) eq(TEST_BASE_URL),
eq(TEST_SERVER_VERSION),
) )
} returns TEST_TOKEN } returns TEST_TOKEN
coEvery { serverInfoStorage.requireBaseURL() } returns TEST_BASE_URL coEvery { serverInfoRepo.requireUrl() } returns TEST_BASE_URL
subject.authenticate(TEST_USERNAME, TEST_PASSWORD) subject.authenticate(TEST_USERNAME, TEST_PASSWORD)
coVerifyAll { coVerifyAll {
storage.setAuthHeader(TEST_AUTH_HEADER) storage.setAuthHeader(TEST_AUTH_HEADER)
@@ -71,8 +74,8 @@ class AuthRepoImplTest {
@Test @Test
fun `when authenticate fails then does not change storage`() = runTest { fun `when authenticate fails then does not change storage`() = runTest {
coEvery { dataSource.authenticate(any(), any(), any()) } throws RuntimeException() coEvery { dataSource.authenticate(any(), any(), any(), any()) } throws RuntimeException()
coEvery { serverInfoStorage.requireBaseURL() } returns TEST_BASE_URL coEvery { serverInfoRepo.requireUrl() } returns TEST_BASE_URL
runCatchingExceptCancel { subject.authenticate("invalid", "") } runCatchingExceptCancel { subject.authenticate("invalid", "") }
confirmVerified(storage) confirmVerified(storage)
} }
@@ -108,13 +111,18 @@ class AuthRepoImplTest {
fun `when invalidate with credentials then calls authenticate`() = runTest { fun `when invalidate with credentials then calls authenticate`() = runTest {
coEvery { storage.getEmail() } returns TEST_USERNAME coEvery { storage.getEmail() } returns TEST_USERNAME
coEvery { storage.getPassword() } returns TEST_PASSWORD coEvery { storage.getPassword() } returns TEST_PASSWORD
coEvery { serverInfoStorage.requireBaseURL() } returns TEST_BASE_URL coEvery { serverInfoRepo.getVersion() } returns TEST_SERVER_VERSION
coEvery { serverInfoRepo.requireUrl() } returns TEST_BASE_URL
coEvery { coEvery {
dataSource.authenticate(eq(TEST_USERNAME), eq(TEST_PASSWORD), eq(TEST_BASE_URL)) dataSource.authenticate(
eq(TEST_USERNAME), eq(TEST_PASSWORD), eq(TEST_BASE_URL), eq(TEST_SERVER_VERSION)
)
} returns TEST_TOKEN } returns TEST_TOKEN
subject.invalidateAuthHeader() subject.invalidateAuthHeader()
coVerifyAll { coVerifyAll {
dataSource.authenticate(eq(TEST_USERNAME), eq(TEST_PASSWORD), eq(TEST_BASE_URL)) dataSource.authenticate(
eq(TEST_USERNAME), eq(TEST_PASSWORD), eq(TEST_BASE_URL), eq(TEST_SERVER_VERSION)
)
} }
} }
@@ -122,8 +130,8 @@ class AuthRepoImplTest {
fun `when invalidate with credentials and auth fails then clears email`() = runTest { fun `when invalidate with credentials and auth fails then clears email`() = runTest {
coEvery { storage.getEmail() } returns "invalid" coEvery { storage.getEmail() } returns "invalid"
coEvery { storage.getPassword() } returns "" coEvery { storage.getPassword() } returns ""
coEvery { serverInfoStorage.requireBaseURL() } returns TEST_BASE_URL coEvery { serverInfoRepo.requireUrl() } returns TEST_BASE_URL
coEvery { dataSource.authenticate(any(), any(), any()) } throws RuntimeException() coEvery { dataSource.authenticate(any(), any(), any(), any()) } throws RuntimeException()
subject.invalidateAuthHeader() subject.invalidateAuthHeader()
coVerify { storage.setEmail(null) } coVerify { storage.setEmail(null) }
} }

View File

@@ -23,12 +23,14 @@ class ServerInfoStorageImplTest {
lateinit var subject: ServerInfoStorage lateinit var subject: ServerInfoStorage
private val baseUrlKey = stringPreferencesKey("baseUrlKey") private val baseUrlKey = stringPreferencesKey("baseUrlKey")
private val serverVersionKey = stringPreferencesKey("serverVersionKey")
@Before @Before
fun setUp() { fun setUp() {
MockKAnnotations.init(this) MockKAnnotations.init(this)
subject = ServerInfoStorageImpl(preferencesStorage) subject = ServerInfoStorageImpl(preferencesStorage)
every { preferencesStorage.baseUrlKey } returns baseUrlKey every { preferencesStorage.baseUrlKey } returns baseUrlKey
every { preferencesStorage.serverVersionKey } returns serverVersionKey
} }
@Test @Test
@@ -37,30 +39,21 @@ class ServerInfoStorageImplTest {
assertThat(subject.getBaseURL()).isNull() assertThat(subject.getBaseURL()).isNull()
} }
@Test(expected = IllegalStateException::class)
fun `when requireBaseURL and preferences storage empty then IllegalStateException`() = runTest {
coEvery { preferencesStorage.getValue(eq(baseUrlKey)) } returns null
subject.requireBaseURL()
}
@Test @Test
fun `when getBaseUrl and preferences storage has value then value`() = runTest { fun `when getBaseUrl and preferences storage has value then value`() = runTest {
coEvery { preferencesStorage.getValue(eq(baseUrlKey)) } returns "baseUrl" coEvery { preferencesStorage.getValue(eq(baseUrlKey)) } returns "baseUrl"
assertThat(subject.getBaseURL()).isEqualTo("baseUrl") assertThat(subject.getBaseURL()).isEqualTo("baseUrl")
} }
@Test
fun `when requireBaseURL and preferences storage has value then value`() = runTest {
coEvery { preferencesStorage.getValue(eq(baseUrlKey)) } returns "baseUrl"
assertThat(subject.requireBaseURL()).isEqualTo("baseUrl")
}
@Test @Test
fun `when storeBaseURL then calls preferences storage`() = runTest { fun `when storeBaseURL then calls preferences storage`() = runTest {
subject.storeBaseURL("baseUrl", "v0.5.6") subject.storeBaseURL("baseUrl", "v0.5.6")
coVerify { coVerify {
preferencesStorage.baseUrlKey preferencesStorage.baseUrlKey
preferencesStorage.storeValues(eq(Pair(baseUrlKey, "baseUrl"))) preferencesStorage.storeValues(
eq(Pair(baseUrlKey, "baseUrl")),
eq(Pair(serverVersionKey, "v0.5.6")),
)
} }
} }
} }

View File

@@ -1,16 +1,19 @@
package gq.kirmanak.mealient.data.network package gq.kirmanak.mealient.data.network
import gq.kirmanak.mealient.data.auth.AuthRepo import gq.kirmanak.mealient.data.auth.AuthRepo
import gq.kirmanak.mealient.data.baseurl.ServerInfoStorage 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.v0.models.GetRecipeResponseV0
import gq.kirmanak.mealient.datasource.v1.MealieDataSourceV1
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.RecipeImplTestData.GET_CAKE_RESPONSE import gq.kirmanak.mealient.test.AuthImplTestData.TEST_SERVER_VERSION
import io.mockk.MockKAnnotations import io.mockk.MockKAnnotations
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.coVerifyAll import io.mockk.coVerifyAll
import io.mockk.impl.annotations.MockK import io.mockk.impl.annotations.MockK
import io.mockk.mockk
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Before import org.junit.Before
@@ -18,35 +21,40 @@ import org.junit.Test
import java.io.IOException import java.io.IOException
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class MealieDataSourceV0WrapperTest { class MealieDataSourceWrapperTest {
@MockK @MockK
lateinit var serverInfoStorage: ServerInfoStorage lateinit var serverInfoRepo: ServerInfoRepo
@MockK(relaxUnitFun = true) @MockK(relaxUnitFun = true)
lateinit var authRepo: AuthRepo lateinit var authRepo: AuthRepo
@MockK @MockK
lateinit var mealieDataSourceV0: MealieDataSourceV0 lateinit var v0Source: MealieDataSourceV0
@MockK
lateinit var v1Source: MealieDataSourceV1
lateinit var subject: MealieDataSourceWrapper lateinit var subject: MealieDataSourceWrapper
@Before @Before
fun setUp() { fun setUp() {
MockKAnnotations.init(this) MockKAnnotations.init(this)
subject = MealieDataSourceWrapper(serverInfoStorage, authRepo, mealieDataSourceV0) subject = MealieDataSourceWrapper(serverInfoRepo, authRepo, v0Source, v1Source)
} }
@Test @Test
fun `when withAuthHeader fails with Unauthorized then invalidates auth`() = runTest { fun `when withAuthHeader fails with Unauthorized then invalidates auth`() = runTest {
coEvery { serverInfoStorage.requireBaseURL() } returns TEST_BASE_URL coEvery { serverInfoRepo.getVersion() } returns TEST_SERVER_VERSION
coEvery { serverInfoRepo.requireUrl() } returns TEST_BASE_URL
coEvery { authRepo.getAuthHeader() } returns null andThen TEST_AUTH_HEADER coEvery { authRepo.getAuthHeader() } returns null andThen TEST_AUTH_HEADER
coEvery { coEvery {
mealieDataSourceV0.requestRecipeInfo(eq(TEST_BASE_URL), isNull(), eq("cake")) v0Source.requestRecipeInfo(eq(TEST_BASE_URL), isNull(), eq("cake"))
} throws NetworkError.Unauthorized(IOException()) } throws NetworkError.Unauthorized(IOException())
val successResponse = mockk<GetRecipeResponseV0>(relaxed = true)
coEvery { coEvery {
mealieDataSourceV0.requestRecipeInfo(eq(TEST_BASE_URL), eq(TEST_AUTH_HEADER), eq("cake")) v0Source.requestRecipeInfo(eq(TEST_BASE_URL), eq(TEST_AUTH_HEADER), eq("cake"))
} returns GET_CAKE_RESPONSE } returns successResponse
subject.requestRecipeInfo("cake") subject.requestRecipeInfo("cake")
coVerifyAll { coVerifyAll {
authRepo.getAuthHeader() authRepo.getAuthHeader()

View File

@@ -73,10 +73,10 @@ class RecipeStorageImplTest : HiltRobolectricTest() {
subject.saveRecipes(TEST_RECIPE_SUMMARIES) subject.saveRecipes(TEST_RECIPE_SUMMARIES)
val actual = appDb.recipeDao().queryAllCategoryRecipes() val actual = appDb.recipeDao().queryAllCategoryRecipes()
assertThat(actual).containsExactly( assertThat(actual).containsExactly(
CategoryRecipeEntity(categoryId = 1, recipeId = 1), CategoryRecipeEntity(categoryId = 1, recipeId = "1"),
CategoryRecipeEntity(categoryId = 2, recipeId = 1), CategoryRecipeEntity(categoryId = 2, recipeId = "1"),
CategoryRecipeEntity(categoryId = 3, recipeId = 2), CategoryRecipeEntity(categoryId = 3, recipeId = "2"),
CategoryRecipeEntity(categoryId = 2, recipeId = 2) CategoryRecipeEntity(categoryId = 2, recipeId = "2")
) )
} }
@@ -85,10 +85,10 @@ class RecipeStorageImplTest : HiltRobolectricTest() {
subject.saveRecipes(TEST_RECIPE_SUMMARIES) subject.saveRecipes(TEST_RECIPE_SUMMARIES)
val actual = appDb.recipeDao().queryAllTagRecipes() val actual = appDb.recipeDao().queryAllTagRecipes()
assertThat(actual).containsExactly( assertThat(actual).containsExactly(
TagRecipeEntity(tagId = 1, recipeId = 1), TagRecipeEntity(tagId = 1, recipeId = "1"),
TagRecipeEntity(tagId = 2, recipeId = 1), TagRecipeEntity(tagId = 2, recipeId = "1"),
TagRecipeEntity(tagId = 3, recipeId = 2), TagRecipeEntity(tagId = 3, recipeId = "2"),
TagRecipeEntity(tagId = 1, recipeId = 2), TagRecipeEntity(tagId = 1, recipeId = "2"),
) )
} }
@@ -106,8 +106,8 @@ class RecipeStorageImplTest : HiltRobolectricTest() {
subject.refreshAll(listOf(RECIPE_SUMMARY_CAKE)) subject.refreshAll(listOf(RECIPE_SUMMARY_CAKE))
val actual = appDb.recipeDao().queryAllCategoryRecipes() val actual = appDb.recipeDao().queryAllCategoryRecipes()
assertThat(actual).containsExactly( assertThat(actual).containsExactly(
CategoryRecipeEntity(categoryId = 1, recipeId = 1), CategoryRecipeEntity(categoryId = 1, recipeId = "1"),
CategoryRecipeEntity(categoryId = 2, recipeId = 1), CategoryRecipeEntity(categoryId = 2, recipeId = "1"),
) )
} }
@@ -117,8 +117,8 @@ class RecipeStorageImplTest : HiltRobolectricTest() {
subject.refreshAll(listOf(RECIPE_SUMMARY_CAKE)) subject.refreshAll(listOf(RECIPE_SUMMARY_CAKE))
val actual = appDb.recipeDao().queryAllTagRecipes() val actual = appDb.recipeDao().queryAllTagRecipes()
assertThat(actual).containsExactly( assertThat(actual).containsExactly(
TagRecipeEntity(tagId = 1, recipeId = 1), TagRecipeEntity(tagId = 1, recipeId = "1"),
TagRecipeEntity(tagId = 2, recipeId = 1), TagRecipeEntity(tagId = 2, recipeId = "1"),
) )
} }
@@ -150,7 +150,7 @@ class RecipeStorageImplTest : HiltRobolectricTest() {
fun `when saveRecipeInfo then saves recipe info`() = runTest { fun `when saveRecipeInfo then saves recipe info`() = runTest {
subject.saveRecipes(listOf(RECIPE_SUMMARY_CAKE)) subject.saveRecipes(listOf(RECIPE_SUMMARY_CAKE))
subject.saveRecipeInfo(GET_CAKE_RESPONSE) subject.saveRecipeInfo(GET_CAKE_RESPONSE)
val actual = appDb.recipeDao().queryFullRecipeInfo(1) val actual = appDb.recipeDao().queryFullRecipeInfo("1")
assertThat(actual).isEqualTo(FULL_CAKE_INFO_ENTITY) assertThat(actual).isEqualTo(FULL_CAKE_INFO_ENTITY)
} }
@@ -159,7 +159,7 @@ class RecipeStorageImplTest : HiltRobolectricTest() {
subject.saveRecipes(listOf(RECIPE_SUMMARY_CAKE, RECIPE_SUMMARY_PORRIDGE)) subject.saveRecipes(listOf(RECIPE_SUMMARY_CAKE, RECIPE_SUMMARY_PORRIDGE))
subject.saveRecipeInfo(GET_CAKE_RESPONSE) subject.saveRecipeInfo(GET_CAKE_RESPONSE)
subject.saveRecipeInfo(GET_PORRIDGE_RESPONSE) subject.saveRecipeInfo(GET_PORRIDGE_RESPONSE)
val actual = appDb.recipeDao().queryFullRecipeInfo(2) val actual = appDb.recipeDao().queryFullRecipeInfo("2")
assertThat(actual).isEqualTo(FULL_PORRIDGE_INFO_ENTITY) assertThat(actual).isEqualTo(FULL_PORRIDGE_INFO_ENTITY)
} }
@@ -169,7 +169,7 @@ class RecipeStorageImplTest : HiltRobolectricTest() {
subject.saveRecipeInfo(GET_CAKE_RESPONSE) subject.saveRecipeInfo(GET_CAKE_RESPONSE)
val newRecipe = GET_CAKE_RESPONSE.copy(recipeIngredients = listOf(BREAD_INGREDIENT)) val newRecipe = GET_CAKE_RESPONSE.copy(recipeIngredients = listOf(BREAD_INGREDIENT))
subject.saveRecipeInfo(newRecipe) subject.saveRecipeInfo(newRecipe)
val actual = appDb.recipeDao().queryFullRecipeInfo(1)?.recipeIngredients val actual = appDb.recipeDao().queryFullRecipeInfo("1")?.recipeIngredients
val expected = listOf(CAKE_BREAD_RECIPE_INGREDIENT_ENTITY.copy(localId = 3)) val expected = listOf(CAKE_BREAD_RECIPE_INGREDIENT_ENTITY.copy(localId = 3))
assertThat(actual).isEqualTo(expected) assertThat(actual).isEqualTo(expected)
} }
@@ -180,7 +180,7 @@ class RecipeStorageImplTest : HiltRobolectricTest() {
subject.saveRecipeInfo(GET_CAKE_RESPONSE) subject.saveRecipeInfo(GET_CAKE_RESPONSE)
val newRecipe = GET_CAKE_RESPONSE.copy(recipeInstructions = listOf(MIX_INSTRUCTION)) val newRecipe = GET_CAKE_RESPONSE.copy(recipeInstructions = listOf(MIX_INSTRUCTION))
subject.saveRecipeInfo(newRecipe) subject.saveRecipeInfo(newRecipe)
val actual = appDb.recipeDao().queryFullRecipeInfo(1)?.recipeInstructions val actual = appDb.recipeDao().queryFullRecipeInfo("1")?.recipeInstructions
val expected = listOf(MIX_CAKE_RECIPE_INSTRUCTION_ENTITY.copy(localId = 3)) val expected = listOf(MIX_CAKE_RECIPE_INSTRUCTION_ENTITY.copy(localId = 3))
assertThat(actual).isEqualTo(expected) assertThat(actual).isEqualTo(expected)
} }

View File

@@ -1,7 +1,7 @@
package gq.kirmanak.mealient.data.recipes.impl 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.ServerInfoStorage import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo
import gq.kirmanak.mealient.logging.Logger import gq.kirmanak.mealient.logging.Logger
import io.mockk.MockKAnnotations import io.mockk.MockKAnnotations
import io.mockk.coEvery import io.mockk.coEvery
@@ -17,7 +17,7 @@ class RecipeImageUrlProviderImplTest {
lateinit var subject: RecipeImageUrlProvider lateinit var subject: RecipeImageUrlProvider
@MockK @MockK
lateinit var serverInfoStorage: ServerInfoStorage lateinit var serverInfoRepo: ServerInfoRepo
@MockK(relaxUnitFun = true) @MockK(relaxUnitFun = true)
lateinit var logger: Logger lateinit var logger: Logger
@@ -25,7 +25,7 @@ class RecipeImageUrlProviderImplTest {
@Before @Before
fun setUp() { fun setUp() {
MockKAnnotations.init(this) MockKAnnotations.init(this)
subject = RecipeImageUrlProviderImpl(serverInfoStorage, logger) subject = RecipeImageUrlProviderImpl(serverInfoRepo, logger)
prepareBaseURL("https://google.com/") prepareBaseURL("https://google.com/")
} }
@@ -81,6 +81,6 @@ class RecipeImageUrlProviderImplTest {
} }
private fun prepareBaseURL(baseURL: String?) { private fun prepareBaseURL(baseURL: String?) {
coEvery { serverInfoStorage.getBaseURL() } returns baseURL coEvery { serverInfoRepo.getUrl() } returns baseURL
} }
} }

View File

@@ -47,24 +47,24 @@ class RecipeRepoImplTest {
@Test @Test
fun `when loadRecipeInfo then loads recipe`() = runTest { fun `when loadRecipeInfo then loads recipe`() = runTest {
coEvery { dataSource.requestRecipeInfo(eq("cake")) } returns GET_CAKE_RESPONSE coEvery { dataSource.requestRecipeInfo(eq("cake")) } returns GET_CAKE_RESPONSE
coEvery { storage.queryRecipeInfo(eq(1)) } returns FULL_CAKE_INFO_ENTITY coEvery { storage.queryRecipeInfo(eq("1")) } returns FULL_CAKE_INFO_ENTITY
val actual = subject.loadRecipeInfo(1, "cake") val actual = subject.loadRecipeInfo("1", "cake")
assertThat(actual).isEqualTo(FULL_CAKE_INFO_ENTITY) assertThat(actual).isEqualTo(FULL_CAKE_INFO_ENTITY)
} }
@Test @Test
fun `when loadRecipeInfo then saves to DB`() = runTest { fun `when loadRecipeInfo then saves to DB`() = runTest {
coEvery { dataSource.requestRecipeInfo(eq("cake")) } returns GET_CAKE_RESPONSE coEvery { dataSource.requestRecipeInfo(eq("cake")) } returns GET_CAKE_RESPONSE
coEvery { storage.queryRecipeInfo(eq(1)) } returns FULL_CAKE_INFO_ENTITY coEvery { storage.queryRecipeInfo(eq("1")) } returns FULL_CAKE_INFO_ENTITY
subject.loadRecipeInfo(1, "cake") subject.loadRecipeInfo("1", "cake")
coVerify { storage.saveRecipeInfo(eq(GET_CAKE_RESPONSE)) } coVerify { storage.saveRecipeInfo(eq(GET_CAKE_RESPONSE)) }
} }
@Test @Test
fun `when loadRecipeInfo with error then loads from DB`() = runTest { fun `when loadRecipeInfo with error then loads from DB`() = runTest {
coEvery { dataSource.requestRecipeInfo(eq("cake")) } throws RuntimeException() coEvery { dataSource.requestRecipeInfo(eq("cake")) } throws RuntimeException()
coEvery { storage.queryRecipeInfo(eq(1)) } returns FULL_CAKE_INFO_ENTITY coEvery { storage.queryRecipeInfo(eq("1")) } returns FULL_CAKE_INFO_ENTITY
val actual = subject.loadRecipeInfo(1, "cake") val actual = subject.loadRecipeInfo("1", "cake")
assertThat(actual).isEqualTo(FULL_CAKE_INFO_ENTITY) assertThat(actual).isEqualTo(FULL_CAKE_INFO_ENTITY)
} }
} }

View File

@@ -1,11 +1,13 @@
package gq.kirmanak.mealient.test package gq.kirmanak.mealient.test
import gq.kirmanak.mealient.data.baseurl.ServerVersion
object AuthImplTestData { object AuthImplTestData {
const val TEST_USERNAME = "TEST_USERNAME" const val TEST_USERNAME = "TEST_USERNAME"
const val TEST_PASSWORD = "TEST_PASSWORD" const val TEST_PASSWORD = "TEST_PASSWORD"
const val TEST_BASE_URL = "https://example.com/" const val TEST_BASE_URL = "https://example.com/"
const val TEST_TOKEN = "TEST_TOKEN" const val TEST_TOKEN = "TEST_TOKEN"
const val TEST_AUTH_HEADER = "Bearer TEST_TOKEN" const val TEST_AUTH_HEADER = "Bearer TEST_TOKEN"
const val TEST_URL = "TEST_URL"
const val TEST_VERSION = "v0.5.6" const val TEST_VERSION = "v0.5.6"
val TEST_SERVER_VERSION = ServerVersion.V0
} }

View File

@@ -1,16 +1,16 @@
package gq.kirmanak.mealient.test package gq.kirmanak.mealient.test
import gq.kirmanak.mealient.data.recipes.network.FullRecipeInfo
import gq.kirmanak.mealient.data.recipes.network.RecipeIngredientInfo
import gq.kirmanak.mealient.data.recipes.network.RecipeInstructionInfo
import gq.kirmanak.mealient.data.recipes.network.RecipeSummaryInfo
import gq.kirmanak.mealient.database.recipe.entity.* import gq.kirmanak.mealient.database.recipe.entity.*
import gq.kirmanak.mealient.datasource.v0.models.GetRecipeIngredientResponseV0
import gq.kirmanak.mealient.datasource.v0.models.GetRecipeInstructionResponseV0
import gq.kirmanak.mealient.datasource.v0.models.GetRecipeResponseV0
import gq.kirmanak.mealient.datasource.v0.models.GetRecipeSummaryResponseV0
import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDate
import kotlinx.datetime.LocalDateTime import kotlinx.datetime.LocalDateTime
object RecipeImplTestData { object RecipeImplTestData {
val RECIPE_SUMMARY_CAKE = GetRecipeSummaryResponseV0( val RECIPE_SUMMARY_CAKE = RecipeSummaryInfo(
remoteId = 1, remoteId = "1",
name = "Cake", name = "Cake",
slug = "cake", slug = "cake",
image = "86", image = "86",
@@ -20,10 +20,11 @@ object RecipeImplTestData {
rating = 4, rating = 4,
dateAdded = LocalDate.parse("2021-11-13"), dateAdded = LocalDate.parse("2021-11-13"),
dateUpdated = LocalDateTime.parse("2021-11-13T15:30:13"), dateUpdated = LocalDateTime.parse("2021-11-13T15:30:13"),
imageId = "cake",
) )
val RECIPE_SUMMARY_PORRIDGE = GetRecipeSummaryResponseV0( val RECIPE_SUMMARY_PORRIDGE = RecipeSummaryInfo(
remoteId = 2, remoteId = "2",
name = "Porridge", name = "Porridge",
slug = "porridge", slug = "porridge",
image = "89", image = "89",
@@ -33,23 +34,25 @@ object RecipeImplTestData {
rating = 5, rating = 5,
dateAdded = LocalDate.parse("2021-11-12"), dateAdded = LocalDate.parse("2021-11-12"),
dateUpdated = LocalDateTime.parse("2021-10-13T17:35:23"), dateUpdated = LocalDateTime.parse("2021-10-13T17:35:23"),
imageId = "porridge",
) )
val TEST_RECIPE_SUMMARIES = listOf(RECIPE_SUMMARY_CAKE, RECIPE_SUMMARY_PORRIDGE) val TEST_RECIPE_SUMMARIES = listOf(RECIPE_SUMMARY_CAKE, RECIPE_SUMMARY_PORRIDGE)
val CAKE_RECIPE_SUMMARY_ENTITY = RecipeSummaryEntity( val CAKE_RECIPE_SUMMARY_ENTITY = RecipeSummaryEntity(
remoteId = 1, remoteId = "1",
name = "Cake", name = "Cake",
slug = "cake", slug = "cake",
image = "86", image = "86",
description = "A tasty cake", description = "A tasty cake",
rating = 4, rating = 4,
dateAdded = LocalDate.parse("2021-11-13"), dateAdded = LocalDate.parse("2021-11-13"),
dateUpdated = LocalDateTime.parse("2021-11-13T15:30:13") dateUpdated = LocalDateTime.parse("2021-11-13T15:30:13"),
imageId = "cake",
) )
val PORRIDGE_RECIPE_SUMMARY_ENTITY = RecipeSummaryEntity( val PORRIDGE_RECIPE_SUMMARY_ENTITY = RecipeSummaryEntity(
remoteId = 2, remoteId = "2",
name = "Porridge", name = "Porridge",
slug = "porridge", slug = "porridge",
image = "89", image = "89",
@@ -57,52 +60,53 @@ object RecipeImplTestData {
rating = 5, rating = 5,
dateAdded = LocalDate.parse("2021-11-12"), dateAdded = LocalDate.parse("2021-11-12"),
dateUpdated = LocalDateTime.parse("2021-10-13T17:35:23"), dateUpdated = LocalDateTime.parse("2021-10-13T17:35:23"),
imageId = "porridge",
) )
private val SUGAR_INGREDIENT = GetRecipeIngredientResponseV0( private val SUGAR_INGREDIENT = RecipeIngredientInfo(
title = "Sugar", title = "Sugar",
note = "2 oz of white sugar", note = "2 oz of white sugar",
unit = "", unit = "",
food = "", food = "",
disableAmount = true, disableAmount = true,
quantity = 1 quantity = 1.0
) )
val BREAD_INGREDIENT = GetRecipeIngredientResponseV0( val BREAD_INGREDIENT = RecipeIngredientInfo(
title = "Bread", title = "Bread",
note = "2 oz of white bread", note = "2 oz of white bread",
unit = "", unit = "",
food = "", food = "",
disableAmount = false, disableAmount = false,
quantity = 2 quantity = 2.0
) )
private val MILK_INGREDIENT = GetRecipeIngredientResponseV0( private val MILK_INGREDIENT = RecipeIngredientInfo(
title = "Milk", title = "Milk",
note = "2 oz of white milk", note = "2 oz of white milk",
unit = "", unit = "",
food = "", food = "",
disableAmount = true, disableAmount = true,
quantity = 3 quantity = 3.0
) )
val MIX_INSTRUCTION = GetRecipeInstructionResponseV0( val MIX_INSTRUCTION = RecipeInstructionInfo(
title = "Mix", title = "Mix",
text = "Mix the ingredients" text = "Mix the ingredients"
) )
private val BAKE_INSTRUCTION = GetRecipeInstructionResponseV0( private val BAKE_INSTRUCTION = RecipeInstructionInfo(
title = "Bake", title = "Bake",
text = "Bake the ingredients" text = "Bake the ingredients"
) )
private val BOIL_INSTRUCTION = GetRecipeInstructionResponseV0( private val BOIL_INSTRUCTION = RecipeInstructionInfo(
title = "Boil", title = "Boil",
text = "Boil the ingredients" text = "Boil the ingredients"
) )
val GET_CAKE_RESPONSE = GetRecipeResponseV0( val GET_CAKE_RESPONSE = FullRecipeInfo(
remoteId = 1, remoteId = "1",
name = "Cake", name = "Cake",
slug = "cake", slug = "cake",
image = "86", image = "86",
@@ -117,8 +121,8 @@ object RecipeImplTestData {
recipeInstructions = listOf(MIX_INSTRUCTION, BAKE_INSTRUCTION) recipeInstructions = listOf(MIX_INSTRUCTION, BAKE_INSTRUCTION)
) )
val GET_PORRIDGE_RESPONSE = GetRecipeResponseV0( val GET_PORRIDGE_RESPONSE = FullRecipeInfo(
remoteId = 2, remoteId = "2",
name = "Porridge", name = "Porridge",
slug = "porridge", slug = "porridge",
image = "89", image = "89",
@@ -135,43 +139,43 @@ object RecipeImplTestData {
val MIX_CAKE_RECIPE_INSTRUCTION_ENTITY = RecipeInstructionEntity( val MIX_CAKE_RECIPE_INSTRUCTION_ENTITY = RecipeInstructionEntity(
localId = 1, localId = 1,
recipeId = 1, recipeId = "1",
title = "Mix", title = "Mix",
text = "Mix the ingredients", text = "Mix the ingredients",
) )
private val BAKE_CAKE_RECIPE_INSTRUCTION_ENTITY = RecipeInstructionEntity( private val BAKE_CAKE_RECIPE_INSTRUCTION_ENTITY = RecipeInstructionEntity(
localId = 2, localId = 2,
recipeId = 1, recipeId = "1",
title = "Bake", title = "Bake",
text = "Bake the ingredients", text = "Bake the ingredients",
) )
private val CAKE_RECIPE_ENTITY = RecipeEntity( private val CAKE_RECIPE_ENTITY = RecipeEntity(
remoteId = 1, remoteId = "1",
recipeYield = "4 servings" recipeYield = "4 servings"
) )
private val CAKE_SUGAR_RECIPE_INGREDIENT_ENTITY = RecipeIngredientEntity( private val CAKE_SUGAR_RECIPE_INGREDIENT_ENTITY = RecipeIngredientEntity(
localId = 1, localId = 1,
recipeId = 1, recipeId = "1",
title = "Sugar", title = "Sugar",
note = "2 oz of white sugar", note = "2 oz of white sugar",
unit = "", unit = "",
food = "", food = "",
disableAmount = true, disableAmount = true,
quantity = 1 quantity = 1.0
) )
val CAKE_BREAD_RECIPE_INGREDIENT_ENTITY = RecipeIngredientEntity( val CAKE_BREAD_RECIPE_INGREDIENT_ENTITY = RecipeIngredientEntity(
localId = 2, localId = 2,
recipeId = 1, recipeId = "1",
title = "Bread", title = "Bread",
note = "2 oz of white bread", note = "2 oz of white bread",
unit = "", unit = "",
food = "", food = "",
disableAmount = false, disableAmount = false,
quantity = 2 quantity = 2.0
) )
val FULL_CAKE_INFO_ENTITY = FullRecipeEntity( val FULL_CAKE_INFO_ENTITY = FullRecipeEntity(
@@ -188,42 +192,42 @@ object RecipeImplTestData {
) )
private val PORRIDGE_RECIPE_ENTITY_FULL = RecipeEntity( private val PORRIDGE_RECIPE_ENTITY_FULL = RecipeEntity(
remoteId = 2, remoteId = "2",
recipeYield = "3 servings" recipeYield = "3 servings"
) )
private val PORRIDGE_MILK_RECIPE_INGREDIENT_ENTITY = RecipeIngredientEntity( private val PORRIDGE_MILK_RECIPE_INGREDIENT_ENTITY = RecipeIngredientEntity(
localId = 4, localId = 4,
recipeId = 2, recipeId = "2",
title = "Milk", title = "Milk",
note = "2 oz of white milk", note = "2 oz of white milk",
unit = "", unit = "",
food = "", food = "",
disableAmount = true, disableAmount = true,
quantity = 3 quantity = 3.0
) )
private val PORRIDGE_SUGAR_RECIPE_INGREDIENT_ENTITY = RecipeIngredientEntity( private val PORRIDGE_SUGAR_RECIPE_INGREDIENT_ENTITY = RecipeIngredientEntity(
localId = 3, localId = 3,
recipeId = 2, recipeId = "2",
title = "Sugar", title = "Sugar",
note = "2 oz of white sugar", note = "2 oz of white sugar",
unit = "", unit = "",
food = "", food = "",
disableAmount = true, disableAmount = true,
quantity = 1 quantity = 1.0
) )
private val PORRIDGE_MIX_RECIPE_INSTRUCTION_ENTITY = RecipeInstructionEntity( private val PORRIDGE_MIX_RECIPE_INSTRUCTION_ENTITY = RecipeInstructionEntity(
localId = 3, localId = 3,
recipeId = 2, recipeId = "2",
title = "Mix", title = "Mix",
text = "Mix the ingredients" text = "Mix the ingredients"
) )
private val PORRIDGE_BOIL_RECIPE_INSTRUCTION_ENTITY = RecipeInstructionEntity( private val PORRIDGE_BOIL_RECIPE_INSTRUCTION_ENTITY = RecipeInstructionEntity(
localId = 4, localId = 4,
recipeId = 2, recipeId = "2",
title = "Boil", title = "Boil",
text = "Boil the ingredients" text = "Boil the ingredients"
) )

View File

@@ -1,6 +1,6 @@
package gq.kirmanak.mealient.ui.baseurl package gq.kirmanak.mealient.ui.baseurl
import gq.kirmanak.mealient.data.baseurl.ServerInfoStorage 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.logging.Logger import gq.kirmanak.mealient.logging.Logger
@@ -21,7 +21,7 @@ import org.junit.Test
class BaseURLViewModelTest : RobolectricTest() { class BaseURLViewModelTest : RobolectricTest() {
@MockK(relaxUnitFun = true) @MockK(relaxUnitFun = true)
lateinit var serverInfoStorage: ServerInfoStorage lateinit var serverInfoRepo: ServerInfoRepo
@MockK @MockK
lateinit var versionDataSource: VersionDataSource lateinit var versionDataSource: VersionDataSource
@@ -34,7 +34,7 @@ class BaseURLViewModelTest : RobolectricTest() {
@Before @Before
fun setUp() { fun setUp() {
MockKAnnotations.init(this) MockKAnnotations.init(this)
subject = BaseURLViewModel(serverInfoStorage, versionDataSource, logger) subject = BaseURLViewModel(serverInfoRepo, versionDataSource, logger)
} }
@Test @Test
@@ -44,6 +44,6 @@ class BaseURLViewModelTest : RobolectricTest() {
} returns VersionInfo(TEST_VERSION) } returns VersionInfo(TEST_VERSION)
subject.saveBaseUrl(TEST_BASE_URL) subject.saveBaseUrl(TEST_BASE_URL)
advanceUntilIdle() advanceUntilIdle()
coVerify { serverInfoStorage.storeBaseURL(eq(TEST_BASE_URL), eq(TEST_VERSION)) } coVerify { serverInfoRepo.storeBaseURL(eq(TEST_BASE_URL), eq(TEST_VERSION)) }
} }
} }

View File

@@ -4,7 +4,6 @@ import gq.kirmanak.mealient.datasource.NetworkError
import gq.kirmanak.mealient.datasource.NetworkRequestWrapper import gq.kirmanak.mealient.datasource.NetworkRequestWrapper
import gq.kirmanak.mealient.datasource.decode import gq.kirmanak.mealient.datasource.decode
import gq.kirmanak.mealient.datasource.v0.models.* import gq.kirmanak.mealient.datasource.v0.models.*
import gq.kirmanak.mealient.logging.Logger
import kotlinx.serialization.SerializationException import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import retrofit2.HttpException import retrofit2.HttpException
@@ -16,7 +15,6 @@ import javax.inject.Singleton
@Singleton @Singleton
class MealieDataSourceV0Impl @Inject constructor( class MealieDataSourceV0Impl @Inject constructor(
private val networkRequestWrapper: NetworkRequestWrapper, private val networkRequestWrapper: NetworkRequestWrapper,
private val logger: Logger,
private val service: MealieServiceV0, private val service: MealieServiceV0,
private val json: Json, private val json: Json,
) : MealieDataSourceV0 { ) : MealieDataSourceV0 {

View File

@@ -35,7 +35,8 @@ class MealieDataSourceV0ImplTest {
@Before @Before
fun setUp() { fun setUp() {
MockKAnnotations.init(this) MockKAnnotations.init(this)
subject = MealieDataSourceV0Impl(logger, service, Json) val networkRequestWrapper: NetworkRequestWrapper = NetworkRequestWrapperImpl(logger)
subject = MealieDataSourceV0Impl(networkRequestWrapper, service, Json)
} }
@Test(expected = NetworkError.NotMealie::class) @Test(expected = NetworkError.NotMealie::class)
@@ -113,6 +114,5 @@ class MealieDataSourceV0ImplTest {
const val TEST_PASSWORD = "TEST_PASSWORD" const val TEST_PASSWORD = "TEST_PASSWORD"
const val TEST_BASE_URL = "https://example.com/" const val TEST_BASE_URL = "https://example.com/"
const val TEST_TOKEN = "TEST_TOKEN" const val TEST_TOKEN = "TEST_TOKEN"
const val TEST_AUTH_HEADER = "Bearer TEST_TOKEN"
} }
} }