# Chapter 11 - Testing the ArtViewModel

Now we will code the class **ArtViewModelTest**, which validates that the **ArtViewModel** in chapter 10 correctly collects and exposes data from the domain layer (via the GetArtUseCase).

```kotlin
package com.learning.artsnapapp.presentation.viewmodel

import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import com.learning.artsnapapp.domain.model.Art
import com.learning.artsnapapp.domain.repository.ArtRepositoryInterface
import com.learning.artsnapapp.domain.usecase.GetArtUseCase
import com.learning.artsnapapp.util.Resource
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test

/**
 * Unit test class for [ArtViewModel].
 *
 * This class ensures that:
 * - The ViewModel correctly collects Flow<List<Art>> from the [GetArtUseCase].
 * - The UI state ([ArtUiState]) updates as expected when the use case emits data.
 * - No Android framework dependency exists; it runs as a pure Kotlin test.
 *
 * The test uses a [FakeRepository] that simulates database operations without touching Room.
 */
@OptIn(ExperimentalCoroutinesApi::class)
class ArtViewModelTest {

    /**
     * Fake repository implementing the domain repository interface.
     * Exposes fakeArtList so tests can assert against the same data.
     */
    class FakeRepository : ArtRepositoryInterface {
        val fakeArtList = listOf(
            Art(id = 1, name = "Bensy Dimo", artistName = "Genry Vale", year = "1889", imageUrl = ""),
            Art(id = 2, name = "The Spench", artistName = "Kivo", year = "1968", imageUrl = "")
        )

        override fun getArt(): Flow<List<Art>> = flowOf(fakeArtList)
        override fun insertArt(art: Art) {}
        override fun deleteArt(art: Art) {}
        override fun searchImage(userQuery: String) = flowOf(Resource.success(emptyList()))
    }

    private lateinit var fakeRepository: FakeRepository
    private lateinit var getArtUseCase: GetArtUseCase
    private lateinit var viewModel: ArtViewModel

    @Before
    fun setUp() {
        fakeRepository = FakeRepository()
        getArtUseCase = GetArtUseCase(fakeRepository)
        viewModel = ArtViewModel(getArtUseCase)
    }

    @Test
    fun `arts StateFlow emits expected art list after initialization`() = runTest {
        val expected = fakeRepository.fakeArtList

        // ArtViewModel.arts is a StateFlow that initially emits emptyList(), then updates.
        viewModel.arts.test {
            val first = awaitItem() // initial emission from StateFlow (emptyList)
            assertThat(first).isEmpty()

            val second = awaitItem() // next emission should be the fake data
            assertThat(second).isEqualTo(expected)

            cancelAndIgnoreRemainingEvents()
        }
    }

    @Test
    fun `errorMessage is null initially`() = runTest {
        viewModel.errorMessage.test {
            val message = awaitItem()
            assertThat(message).isNull()
            cancelAndIgnoreRemainingEvents()
        }
    }
}
```

### **First TEST (in the** ArtViewModelTest **class)**

To verify that when the ArtViewModel is initialised, it automatically loads the list of artworks from the repository (through **GetArtUseCase**) and updates the exposed arts StateFlow correctly.

**Flow of control:**

1. ViewModel calls getArtUseCase() inside init → loadArts().
    
2. The use case collects the Flow&lt;List&lt;Art&gt;&gt; from the FakeRepository.
    
3. The repository emits fakeArtList → ViewModel updates \_arts.
    
4. The test collects from viewModel.arts and verifies:
    
    * First emission → emptyList() (initial StateFlow value)
        
    * Second emission → expected fakeArtList
        

**Concepts validated:**

* Correct propagation of data from Repository → UseCase → ViewModel
    
* ViewModel’s **reactive data handling** via StateFlow
    
* No side-effects or missing emissions in initialisation logic
    

**Why this is important:**  
This test confirms that the UI (Compose screen) will **automatically** show the correct list when the ViewModel starts — crucial for reactive UIs in MVVM.

### SECOND TEST (in the ArtViewModel Test class)

To ensure that the **ArtViewModel** does not emit any spurious error messages upon initialisation.

**Flow of control:**

1. ViewModel initialises and triggers loadArts().
    
2. Since FakeRepository doesn’t throw exceptions, \_errorMessage should stay null.
    
3. The test collects viewModel.errorMessage and asserts it’s null.
    

**Concepts validated:**

* Default **UI state correctness** after startup
    
* Proper initialisation of reactive error state flow
    

**Why this is important:**  
Ensures users won’t see any “phantom” errors when the screen first loads — a common issue if state flows are mismanaged or default values are incorrect.

Let us work on the Composable UI and complete the entire flow in the next chapter.
