Skip to content
Open
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
1 change: 1 addition & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ import retrofit2.Retrofit
@OptIn(ExperimentalCoroutinesApi::class)
class UserRepositoryTest {

@get:Rule
val mainDispatcherRule = MainDispatcherRule()

private lateinit var repository: UserRepositoryImpl
private lateinit var api: UserApiFake
private lateinit var mockWebServer: MockWebServer
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.juandgaines.testground.presentation

import androidx.lifecycle.SavedStateHandle
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
import org.junit.Test

@OptIn(ExperimentalCoroutinesApi::class)
class ProfileViewModelTest {

private val testDispatcher = StandardTestDispatcher()

private lateinit var viewModel: ProfileViewModel
private lateinit var repository: UserRepositoryFake

@Before
fun setUp() {
Dispatchers.setMain(testDispatcher)

repository = UserRepositoryFake()
viewModel = ProfileViewModel(
repository = repository,
savedStateHandle = SavedStateHandle(
initialState = mapOf(
"userId" to repository.profileToReturn.user.id
)
)
)
}

@After
fun tearDown() {
Dispatchers.resetMain()
}

@Test
fun givenValidUserId_whenLoadProfile_thenProfileIsLoaded() = runTest {
// Act
viewModel.loadProfile()
advanceUntilIdle()

// Assert
assertThat(viewModel.state.value.profile).isEqualTo(repository.profileToReturn)
assertThat(viewModel.state.value.isLoading).isFalse()
}

@Test
fun givenRepositoryError_whenLoadProfile_thenErrorStateIsSet() = runTest {
// Arrange
repository.errorToReturn = Exception("Test exception")

// Act
viewModel.loadProfile()
advanceUntilIdle()

// Assert
assertThat(viewModel.state.value.profile).isNull()
assertThat(viewModel.state.value.errorMessage).isEqualTo("Test exception")
assertThat(viewModel.state.value.isLoading).isFalse()
}

@Test
fun givenLoadingState_whenLoadProfile_thenStateUpdatesCorrectly() = runTest {
// Act & Assert
viewModel.state.test {
val emission1 = awaitItem()
assertThat(emission1.isLoading).isFalse()

viewModel.loadProfile()

val emission2 = awaitItem()
assertThat(emission2.isLoading).isTrue()

val emission3 = awaitItem()
assertThat(emission3.isLoading).isFalse()
assertThat(emission3.profile).isEqualTo(repository.profileToReturn)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.juandgaines.testground.presentation

import com.juandgaines.testground.domain.Coordinates
import com.juandgaines.testground.domain.Place
import com.juandgaines.testground.domain.Profile
import com.juandgaines.testground.domain.User
import com.juandgaines.testground.domain.UserRepository
import java.util.UUID

class UserRepositoryFake : UserRepository {
var profileToReturn = profile()
var errorToReturn: Exception? = null

override suspend fun getProfile(userId: String): Result<Profile> {
return if (errorToReturn != null) {
Result.failure(errorToReturn!!)
} else Result.success(profileToReturn)
}

override suspend fun getPlaces(userId: String): Result<List<Place>> {
return Result.success(profileToReturn.places)
}
}

private fun user(): User {
return User(
id = UUID.randomUUID().toString(),
username = "test-user"
)
}

private fun place(userId: String): Place {
return Place(
id = UUID.randomUUID().toString(),
name = "test place",
coordinates = Coordinates(1.0, 1.0)
)
}

private fun profile(): Profile {
val user = user()
return Profile(
user = user,
places = (1..10).map {
place(user.id)
}
)
}