Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increase Test Coverage #28

Merged
merged 2 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ class RemindersScreenVM @Inject constructor(
viewModelScope.launch {
_uiState.update { it.copy(isLoading = true) }
getRemindersUseCase()
.catch {
.catch { throwable ->
_uiState.update {
it.copy(
isLoading = false,
infoMessage = it.infoMessage
infoMessage = throwable.localizedMessage
)
}
}
Expand All @@ -54,7 +54,7 @@ class RemindersScreenVM @Inject constructor(
it.copy(
reminders = reminders.toImmutableList(),
isLoading = false,
infoMessage = it.infoMessage
infoMessage = null
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ import com.raghav.spacedawnv2.data.remote.dto.toLaunchDetail
import com.raghav.spacedawnv2.domain.usecase.AddReminderUseCase
import com.raghav.spacedawnv2.util.FakeLaunchesRepository
import com.raghav.spacedawnv2.util.FakeReminderScheduler
import com.raghav.spacedawnv2.util.Helpers.Companion.getDtoFromJson
import com.raghav.spacedawnv2.util.MainDispatcherRule
import com.raghav.spacedawnv2.util.launchDetailDtoString
import com.raghav.spacedawnv2.util.launchesResponseDtoString
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch
Expand All @@ -39,8 +38,6 @@ class LaunchesScreenVMTest {
private lateinit var launchesScreenVM: LaunchesScreenVM
private val fakeReminderScheduler = FakeReminderScheduler()

private val moshi = Moshi.Builder().build()

/*
UiState = LaunchesScreenState(
val launches: List<LaunchDetail> ,
Expand All @@ -53,6 +50,7 @@ class LaunchesScreenVMTest {
initialize(testScheduler = testScheduler)

val result = launchesScreenVM.uiState.value

val launchesResponse =
getDtoFromJson<LaunchesResponseDto>(launchesResponseDtoString)?.toDomain()

Expand Down Expand Up @@ -117,11 +115,4 @@ class LaunchesScreenVMTest {
addReminderUseCase
)
}

private inline fun <reified T> getDtoFromJson(jsonString: String): T? {
val adapter: JsonAdapter<T> =
moshi.adapter(T::class.java)

return adapter.fromJson(jsonString)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package com.raghav.spacedawnv2.remindersscreen

import com.google.common.truth.Truth
import com.raghav.spacedawnv2.data.remote.dto.LaunchesResponseDto
import com.raghav.spacedawnv2.data.remote.dto.toDomain
import com.raghav.spacedawnv2.domain.model.Reminder
import com.raghav.spacedawnv2.domain.model.toReminder
import com.raghav.spacedawnv2.domain.usecase.CancelReminderUseCase
import com.raghav.spacedawnv2.domain.usecase.GetRemindersUseCase
import com.raghav.spacedawnv2.util.FakeReminderScheduler
import com.raghav.spacedawnv2.util.FakeRemindersRepository
import com.raghav.spacedawnv2.util.Helpers.Companion.getDtoFromJson
import com.raghav.spacedawnv2.util.MainDispatcherRule
import com.raghav.spacedawnv2.util.launchesResponseDtoString
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestCoroutineScheduler
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test

@OptIn(ExperimentalCoroutinesApi::class)
class RemindersScreenVMTest {

@get:Rule
val dispatcherRule = MainDispatcherRule()

private lateinit var remindersScreenVM: RemindersScreenVM

/* RemindersScreenState(
val reminders: ImmutableList<Reminder> = persistentListOf(),
val isLoading: Boolean = false,
val infoMessage: String? = "Some Error Occurred"
)
*/

@Test
fun getReminders_errorOccurred_updatesUiState() = runTest {
initialize(false, testScheduler = testScheduler)
val result = remindersScreenVM.uiState.value
val expected = RemindersScreenState(infoMessage = "Some Error Occurred")

Truth.assertThat(result).isEqualTo(expected)
}

/* RemindersScreenState(
val reminders: ImmutableList<Reminder> = remimders,
val isLoading: Boolean = false,
val infoMessage: String? = null
)
*/

@Test
fun getReminders_remindersAvailable_updateUiState() = runTest {
initialize(remindersFetchedSuccessfully = true, testScheduler = testScheduler)
val result = remindersScreenVM.uiState.value

val reminders = createReminders()

val expected = RemindersScreenState(reminders = reminders.toImmutableList())

Truth.assertThat(result).isEqualTo(expected)
}

@Test
fun cancelReminder_removesReminderFromDeviceAndAppDatabase() = runTest {
initialize(testScheduler = testScheduler)

val reminders = createReminders()

var result: RemindersScreenEvent? = null
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
remindersScreenVM.eventFlow.collect {
result = it
}
}
remindersScreenVM.cancelReminder(reminders.first().id)
val expected = RemindersScreenEvent.ReminderCancelled

Truth.assertThat(result).isEqualTo(expected)
}

@Test
fun cancelReminder_inCaseOfFailureEmitFailureEvent() = runTest {
// assuming failure occurred while deleting the reminder from database
initialize(reminderDeletedSuccessfully = false, testScheduler = testScheduler)

val reminders = createReminders()

var result: RemindersScreenEvent? = null
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
remindersScreenVM.eventFlow.collect {
result = it
}
}
remindersScreenVM.cancelReminder(reminders.first().id)
val expected = RemindersScreenEvent.ReminderNotCancelled("Some Error Occurred")

Truth.assertThat(result).isEqualTo(expected)
}

private fun initialize(
remindersFetchedSuccessfully: Boolean = true,
reminderDeletedSuccessfully: Boolean = true,
testScheduler: TestCoroutineScheduler
) {
val fakeRemindersRepository =
FakeRemindersRepository(remindersFetchedSuccessfully, reminderDeletedSuccessfully)
val fakeReminderScheduler = FakeReminderScheduler()
val getReminderUseCase = GetRemindersUseCase(fakeRemindersRepository)
val cancelReminderUseCase =
CancelReminderUseCase(fakeRemindersRepository, fakeReminderScheduler)
remindersScreenVM =
RemindersScreenVM(
cancelReminderUseCase = cancelReminderUseCase,
getRemindersUseCase = getReminderUseCase,
ioDispatcher = UnconfinedTestDispatcher(testScheduler)
)
}

private fun createReminders(): List<Reminder> {
val launchesResponse =
getDtoFromJson<LaunchesResponseDto>(launchesResponseDtoString)?.toDomain()

return launchesResponse?.results?.filterNotNull()?.map {
it.toReminder()
} ?: emptyList()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ class FakeReminderScheduler : ReminderScheduler {
}

override fun cancelReminder(id: String) {
// assume reminder is cancelled by the AlarmManager api
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.raghav.spacedawnv2.util

import com.raghav.spacedawnv2.data.remote.dto.LaunchesResponseDto
import com.raghav.spacedawnv2.data.remote.dto.toDomain
import com.raghav.spacedawnv2.domain.model.Reminder
import com.raghav.spacedawnv2.domain.model.toReminder
import com.raghav.spacedawnv2.domain.repository.RemindersRepository
import com.raghav.spacedawnv2.util.Helpers.Companion.getDtoFromJson
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf

class FakeRemindersRepository(
private val remindersFetchedSuccessfully: Boolean = true,
private val reminderDeletedSuccessfully: Boolean = true
) :
RemindersRepository {

override fun getRemindersFromDb(): Flow<List<Reminder>> {
return if (remindersFetchedSuccessfully) {
val launchesResponse =
getDtoFromJson<LaunchesResponseDto>(launchesResponseDtoString)?.toDomain()

val reminders =
launchesResponse?.results?.filterNotNull()?.map {
it.toReminder()
} ?: emptyList()

flowOf(reminders)
} else {
flow {
throw Throwable(message = "Some Error Occurred")
}
}
}

override suspend fun deleteReminderFromDb(reminderId: String) {
if (reminderDeletedSuccessfully.not()) {
throw Exception("Some Error Occurred")
}
}
}
17 changes: 17 additions & 0 deletions app/src/test/java/com/raghav/spacedawnv2/util/Helpers.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.raghav.spacedawnv2.util

import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi

class Helpers {

companion object {
val moshi: Moshi = Moshi.Builder().build()
inline fun <reified T> getDtoFromJson(jsonString: String): T? {
val adapter: JsonAdapter<T> =
moshi.adapter(T::class.java)

return adapter.fromJson(jsonString)
}
}
}
Loading