Add auth repo and storage tests

This commit is contained in:
Kirill Kamakin
2022-04-08 23:03:36 +05:00
parent 869fa21e3f
commit ad1077510b
3 changed files with 181 additions and 3 deletions

View File

@@ -1,6 +1,7 @@
package gq.kirmanak.mealient.data.auth.impl package gq.kirmanak.mealient.data.auth.impl
import android.content.SharedPreferences import android.content.SharedPreferences
import androidx.annotation.VisibleForTesting
import androidx.core.content.edit import androidx.core.content.edit
import gq.kirmanak.mealient.data.auth.AuthStorage import gq.kirmanak.mealient.data.auth.AuthStorage
import gq.kirmanak.mealient.di.AuthModule.Companion.ENCRYPTED import gq.kirmanak.mealient.di.AuthModule.Companion.ENCRYPTED
@@ -53,8 +54,13 @@ class AuthStorageImpl @Inject constructor(
} }
companion object { companion object {
private const val AUTH_HEADER_KEY = "authHeader" @VisibleForTesting
private const val EMAIL_KEY = "email" const val AUTH_HEADER_KEY = "authHeader"
private const val PASSWORD_KEY = "password"
@VisibleForTesting
const val EMAIL_KEY = "email"
@VisibleForTesting
const val PASSWORD_KEY = "password"
} }
} }

View File

@@ -0,0 +1,108 @@
package gq.kirmanak.mealient.data.auth.impl
import com.google.common.truth.Truth.assertThat
import gq.kirmanak.mealient.data.auth.AuthDataSource
import gq.kirmanak.mealient.data.auth.AuthRepo
import gq.kirmanak.mealient.data.auth.AuthStorage
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_AUTH_HEADER
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_PASSWORD
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_TOKEN
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_USERNAME
import io.mockk.*
import io.mockk.impl.annotations.MockK
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class)
class AuthRepoImplTest {
@MockK
lateinit var dataSource: AuthDataSource
@MockK(relaxUnitFun = true)
lateinit var storage: AuthStorage
lateinit var subject: AuthRepo
@Before
fun setUp() {
MockKAnnotations.init(this)
subject = AuthRepoImpl(storage, dataSource)
}
@Test
fun `when isAuthorizedFlow then reads from storage`() = runTest {
every { storage.authHeaderFlow } returns flowOf("", null, "header")
assertThat(subject.isAuthorizedFlow.toList()).isEqualTo(listOf(true, false, true))
}
@Test
fun `when authenticate successfully then saves to storage`() = runTest {
coEvery { dataSource.authenticate(eq(TEST_USERNAME), eq(TEST_PASSWORD)) } returns TEST_TOKEN
subject.authenticate(TEST_USERNAME, TEST_PASSWORD)
coVerifyAll {
storage.setAuthHeader(TEST_AUTH_HEADER)
storage.setEmail(TEST_USERNAME)
storage.setPassword(TEST_PASSWORD)
}
confirmVerified(storage)
}
@Test
fun `when authenticate fails then does not change storage`() = runTest {
coEvery { dataSource.authenticate(any(), any()) } throws RuntimeException()
runCatching { subject.authenticate("invalid", "") }
confirmVerified(storage)
}
@Test
fun `when logout then removes email, password and header`() = runTest {
subject.logout()
coVerifyAll {
storage.setEmail(null)
storage.setPassword(null)
storage.setAuthHeader(null)
}
confirmVerified(storage)
}
@Test
fun `when invalidate then does not authenticate without email`() = runTest {
coEvery { storage.getEmail() } returns null
coEvery { storage.getPassword() } returns TEST_PASSWORD
subject.invalidateAuthHeader()
confirmVerified(dataSource)
}
@Test
fun `when invalidate then does not authenticate without password`() = runTest {
coEvery { storage.getEmail() } returns TEST_USERNAME
coEvery { storage.getPassword() } returns null
subject.invalidateAuthHeader()
confirmVerified(dataSource)
}
@Test
fun `when invalidate with credentials then calls authenticate`() = runTest {
coEvery { storage.getEmail() } returns TEST_USERNAME
coEvery { storage.getPassword() } returns TEST_PASSWORD
coEvery { dataSource.authenticate(eq(TEST_USERNAME), eq(TEST_PASSWORD)) } returns TEST_TOKEN
subject.invalidateAuthHeader()
coVerifyAll {
dataSource.authenticate(eq(TEST_USERNAME), eq(TEST_PASSWORD))
}
}
@Test
fun `when invalidate with credentials and auth fails then clears email`() = runTest {
coEvery { storage.getEmail() } returns "invalid"
coEvery { storage.getPassword() } returns ""
coEvery { dataSource.authenticate(any(), any()) } throws RuntimeException()
subject.invalidateAuthHeader()
coVerify { storage.setEmail(null) }
}
}

View File

@@ -0,0 +1,64 @@
package gq.kirmanak.mealient.data.auth.impl
import android.content.Context
import android.content.SharedPreferences
import androidx.core.content.edit
import com.google.common.truth.Truth.assertThat
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.testing.HiltAndroidTest
import gq.kirmanak.mealient.data.auth.AuthStorage
import gq.kirmanak.mealient.data.auth.impl.AuthStorageImpl.Companion.AUTH_HEADER_KEY
import gq.kirmanak.mealient.data.auth.impl.AuthStorageImpl.Companion.EMAIL_KEY
import gq.kirmanak.mealient.data.auth.impl.AuthStorageImpl.Companion.PASSWORD_KEY
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_AUTH_HEADER
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_PASSWORD
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_USERNAME
import gq.kirmanak.mealient.test.HiltRobolectricTest
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import javax.inject.Inject
@OptIn(ExperimentalCoroutinesApi::class)
@HiltAndroidTest
class AuthStorageImplTest : HiltRobolectricTest() {
@Inject
@ApplicationContext
lateinit var context: Context
lateinit var subject: AuthStorage
lateinit var sharedPreferences: SharedPreferences
@Before
fun setUp() {
sharedPreferences = context.getSharedPreferences("test", Context.MODE_PRIVATE)
subject = AuthStorageImpl(sharedPreferences)
}
@Test
fun `when authHeaderFlow is observed then sends value immediately`() = runTest {
sharedPreferences.edit(commit = true) { putString(AUTH_HEADER_KEY, TEST_AUTH_HEADER) }
assertThat(subject.authHeaderFlow.first()).isEqualTo(TEST_AUTH_HEADER)
}
@Test
fun `when authHeader is observed then sends null if nothing saved`() = runTest {
assertThat(subject.authHeaderFlow.first()).isEqualTo(null)
}
@Test
fun `when setEmail then edits shared preferences`() = runTest {
subject.setEmail(TEST_USERNAME)
assertThat(sharedPreferences.getString(EMAIL_KEY, null)).isEqualTo(TEST_USERNAME)
}
@Test
fun `when getPassword then reads shared preferences`() = runTest {
sharedPreferences.edit(commit = true) { putString(PASSWORD_KEY, TEST_PASSWORD) }
assertThat(subject.getPassword()).isEqualTo(TEST_PASSWORD)
}
}