google-developer-training / basic-android-kotlin-compose-training-mars-photos

Solution code for Android Basics in Kotlin course
https://developer.android.com/courses/android-basics-kotlin/course?gclid=CjwKCAjw4c-ZBhAEEiwAZ105RTyT-iaLHzrhMBUXdMhO230ZDwOwxxI2x4RgK8DwBxK8t1h0wmU_QxoCi4YQAvD_BwE
Apache License 2.0
72 stars 66 forks source link

MarsViewModelTest is failed #89

Open Gianguyen1234 opened 1 year ago

Gianguyen1234 commented 1 year ago

java.lang.AssertionError: expected:<Success(photos=Success: 2 Mars photos retrieved)> but was:<Success(photos=I got 2 photos)> at org.junit.Assert.fail(Assert.java:89) at org.junit.Assert.failNotEquals(Assert.java:835) at org.junit.Assert.assertEquals(Assert.java:120) at org.junit.Assert.assertEquals(Assert.java:146) at com.example.redplanetview.fake.MarsViewModelTest$marsViewModel_getMarsPhotos_verifyMarsUiStateSuccess$1.invokeSuspend(MarsViewModelTest.kt:26) at com.example.redplanetview.fake.MarsViewModelTest$marsViewModel_getMarsPhotos_verifyMarsUiStateSuccess$1.invoke(MarsViewModelTest.kt) at com.example.redplanetview.fake.MarsViewModelTest$marsViewModel_getMarsPhotos_verifyMarsUiStateSuccess$1.invoke(MarsViewModelTest.kt) at kotlinx.coroutines.test.TestBuildersKtTestBuildersKt$runTestCoroutine$2.invokeSuspend(TestBuilders.kt:212) at kotlinx.coroutines.test.TestBuildersKtTestBuildersKt$runTestCoroutine$2.invoke(TestBuilders.kt) at kotlinx.coroutines.test.TestBuildersKtTestBuildersKt$runTestCoroutine$2.invoke(TestBuilders.kt) at kotlinx.coroutines.intrinsics.UndispatchedKt.startCoroutineUndispatched(Undispatched.kt:55) at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:112) at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126) at kotlinx.coroutines.test.TestBuildersKtTestBuildersKt.runTestCoroutine(TestBuilders.kt:211) at kotlinx.coroutines.test.TestBuildersKt.runTestCoroutine(Unknown Source) at kotlinx.coroutines.test.TestBuildersKtTestBuildersKt$runTest$1$1.invokeSuspend(TestBuilders.kt:167) at kotlinx.coroutines.test.TestBuildersKtTestBuildersKt$runTest$1$1.invoke(TestBuilders.kt) at kotlinx.coroutines.test.TestBuildersKtTestBuildersKt$runTest$1$1.invoke(TestBuilders.kt) at kotlinx.coroutines.test.TestBuildersJvmKt$createTestResult$1.invokeSuspend(TestBuildersJvm.kt:13) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106) at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:284) at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85) at kotlinx.coroutines.BuildersKtBuildersKt.runBlocking(Builders.kt:59) at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source) at kotlinx.coroutines.BuildersKtBuildersKt.runBlocking$default(Builders.kt:38) at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source) at kotlinx.coroutines.test.TestBuildersJvmKt.createTestResult(TestBuildersJvm.kt:12) at kotlinx.coroutines.test.TestBuildersKtTestBuildersKt.runTest(TestBuilders.kt:166) at kotlinx.coroutines.test.TestBuildersKt.runTest(Unknown Source) at kotlinx.coroutines.test.TestBuildersKtTestBuildersKt.runTest(TestBuilders.kt:154) at kotlinx.coroutines.test.TestBuildersKt.runTest(Unknown Source) at kotlinx.coroutines.test.TestBuildersKtTestBuildersKt.runTest$default(TestBuilders.kt:147) at kotlinx.coroutines.test.TestBuildersKt.runTest$default(Unknown Source) at com.example.redplanetview.fake.MarsViewModelTest.marsViewModel_getMarsPhotos_verifyMarsUiStateSuccess(MarsViewModelTest.kt:22)

Gianguyen1234 commented 1 year ago

Here is code: package com.example.redplanetview.fake import com.example.redplanetview.rules.TestDispatcherRule import com.example.redplanetview.screens.MarsUiState import com.example.redplanetview.screens.MarsViewModel import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.junit.Assert.assertEquals import org.junit.Rule import org.junit.Test

class MarsViewModelTest {

@OptIn(ExperimentalCoroutinesApi::class)
@get:Rule
val testDispatcher = TestDispatcherRule()

@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun marsViewModel_getMarsPhotos_verifyMarsUiStateSuccess() =
    runTest {
        val marsViewModel = MarsViewModel(
            marsPhotosRepository = FakeNetworkMarsPhotosRepository()
        )
        assertEquals(
            MarsUiState.Success("Success: ${FakeDataSource.photosList.size} Mars " +
                    "photos retrieved"),
            marsViewModel.marsUiState
        )
    }

}

Gianguyen1234 commented 1 year ago

Here's a new code that passed the test:

package com.example.redplanetview import com.example.redplanetview.fake.FakeDataSource import com.example.redplanetview.fake.FakeNetworkMarsPhotosRepository import com.example.redplanetview.rules.TestDispatcherRule import com.example.redplanetview.screens.MarsUiState import com.example.redplanetview.screens.MarsViewModel import kotlinx.coroutines.test.runTest import org.junit.Assert.assertEquals import org.junit.Rule import org.junit.Test

class MarsViewModelTest {

@get:Rule
val testDispatcher = TestDispatcherRule()

@Test
fun marsViewModel_getMarsPhotos_verifyMarsUiStateSuccess() =
    runTest {
        val marsViewModel = MarsViewModel(
            marsPhotosRepository = FakeNetworkMarsPhotosRepository()
        )
        assertEquals(
            MarsUiState.Success(FakeDataSource.photosList),
            marsViewModel.marsUiState
        )
    }

}

theiqbalpk commented 12 months ago

@Gianguyen1234

MarsViewModel

e: file:///C:/Users/iqbal/AndroidStudioProjects/basic-android-kotlin-compose-training-mars-photos-starter/app/src/main/java/com/example/marsphotos/ui/screens/MarsViewModel.kt:63:21 Type mismatch: inferred type is String but List was expected

MarsViewModel.kt

package com.example.marsphotos.ui.screens

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.example.marsphotos.MarsPhotosApplication
import com.example.marsphotos.data.MarsPhotosRepository
import com.example.marsphotos.network.MarsPhoto
import kotlinx.coroutines.launch
import java.io.IOException

sealed interface MarsUiState {
    data class Success(val photos: String) : MarsUiState
    object Error: MarsUiState
    object Loading: MarsUiState
}

class MarsViewModel(private val marsPhotosRepository: MarsPhotosRepository) : ViewModel() {
    var marsUiState: MarsUiState by mutableStateOf(MarsUiState.Loading)
        private set

init {
        getMarsPhotos()
    }

fun getMarsPhotos() {
        viewModelScope.launch {
            marsUiState = try {
                val listResult = marsPhotosRepository.getMarsPhotos()
                MarsUiState.Success(
                    "Success: ${listResult.size} Mars photos retrieved."
                )
            } catch (e: IOException) {
                MarsUiState.Error
            }
        }
    }

companion object {
        val Factory: ViewModelProvider.Factory = viewModelFactory {
            initializer {
                val application = (this[APPLICATION_KEY] as MarsPhotosApplication)
                val marsPhotosRepository = application.container.marsPhotosRepository
                MarsViewModel(marsPhotosRepository = marsPhotosRepository)
            }
        }
    }
}