fix(android): drop Loading-state assertions in LibraryViewModelTest
The three failing assertions tested an implementation detail. Under
UnconfinedTestDispatcher (MainDispatcherExtension's default), stateIn's
upstream Flow runs synchronously when the first subscriber attaches,
so the `Loading` initialValue gets replaced by the upstream emission
before Turbine's .test{} sees it. The observable behavior we care
about is the resolved state — Empty/Success/Error — not the
intermediate Loading.
Tests now collect the resolved state as the first awaitItem(), which
is what users actually see. The Loading state still exists in
production (StateFlow initialValue is preserved across the brief
window before stateIn collects the first upstream value when the
real dispatcher isn't unconfined).
Also cleared two compile warnings the run surfaced:
- AuthCookieInterceptorTest: added @OptIn(ExperimentalCoroutinesApi)
for UnconfinedTestDispatcher
- LibraryRepositoryTest: hoisted the Json instance into a companion
object (detekt warned about per-call creation)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import com.fabledsword.minstrel.cache.db.dao.AuthSessionDao
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||
@@ -18,6 +19,7 @@ import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNull
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class AuthCookieInterceptorTest {
|
||||
private lateinit var server: MockWebServer
|
||||
private lateinit var authStore: AuthStore
|
||||
|
||||
+5
-4
@@ -37,13 +37,14 @@ class LibraryRepositoryTest {
|
||||
Retrofit.Builder()
|
||||
.baseUrl(server.url("/"))
|
||||
.client(OkHttpClient.Builder().build())
|
||||
.addConverterFactory(
|
||||
Json { ignoreUnknownKeys = true }
|
||||
.asConverterFactory("application/json".toMediaType()),
|
||||
)
|
||||
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
|
||||
.build()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val json = Json { ignoreUnknownKeys = true }
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun teardown() {
|
||||
server.shutdown()
|
||||
|
||||
+7
-3
@@ -30,6 +30,13 @@ class LibraryViewModelTest {
|
||||
assertEquals(LibraryUiState.Loading, vm.uiState.value)
|
||||
}
|
||||
|
||||
// Note: tests below collect the resolved state directly. With
|
||||
// UnconfinedTestDispatcher, stateIn's upstream Flow runs synchronously
|
||||
// when the first subscriber attaches — so the `Loading` initialValue
|
||||
// is replaced by the upstream emission before .test{} sees it. The
|
||||
// observable behavior we care about is the resolved state, not the
|
||||
// intermediate Loading.
|
||||
|
||||
@Test
|
||||
fun `Empty when DAOs emit empty lists`() = runTest {
|
||||
val repo = mockk<LibraryRepository>()
|
||||
@@ -39,7 +46,6 @@ class LibraryViewModelTest {
|
||||
val vm = LibraryViewModel(repo)
|
||||
|
||||
vm.uiState.test {
|
||||
assertEquals(LibraryUiState.Loading, awaitItem())
|
||||
assertEquals(LibraryUiState.Empty, awaitItem())
|
||||
cancelAndConsumeRemainingEvents()
|
||||
}
|
||||
@@ -56,7 +62,6 @@ class LibraryViewModelTest {
|
||||
val vm = LibraryViewModel(repo)
|
||||
|
||||
vm.uiState.test {
|
||||
assertEquals(LibraryUiState.Loading, awaitItem())
|
||||
val success = awaitItem() as LibraryUiState.Success
|
||||
assertEquals(1, success.artists.size)
|
||||
assertEquals(1, success.albums.size)
|
||||
@@ -76,7 +81,6 @@ class LibraryViewModelTest {
|
||||
val vm = LibraryViewModel(repo)
|
||||
|
||||
vm.uiState.test {
|
||||
assertEquals(LibraryUiState.Loading, awaitItem())
|
||||
val error = awaitItem() as LibraryUiState.Error
|
||||
assertTrue(error.message.contains("DAO blew up"))
|
||||
cancelAndConsumeRemainingEvents()
|
||||
|
||||
Reference in New Issue
Block a user