REDI-100: adopt MockK and rewrite unit tests to use it

Replace the hand-written CharacterRepository fakes in the ViewModel and
UseCase unit tests with MockK mocks (coEvery / coVerify). This is a
deliberate showcase of MockK and intentionally diverges from the repo's
"prefer fakes over mocks" guidance.

- Add io.mockk:mockk 1.14.3 to the version catalog and the unit-test bundle;
  add it explicitly to DomainModuleConventionPlugin (domain does not consume
  the bundle).
- CharacterListViewModelTest: strict mockk, per-page coEvery stubs; the
  paging/in-flight guards are expressed via coVerify(exactly = ...) and
  coVerifyOrder instead of fake call counters.
- CharacterDetailViewModelTest: relaxed mockk so "missing id" needs no
  stubbing; explicit coEvery elsewhere.
- GetCharactersPageUseCaseTest: mockk + coVerify replaces the inline fake.
- Move character()/characterDetails() fixtures to CharacterFixtures.kt and
  delete FakeCharacterRepository.kt.
- NetworkCharacterRepositoryTest stays on Ktor MockEngine (MockK is for
  Kotlin collaborator interfaces, not the HTTP transport).
This commit is contained in:
2026-06-10 15:53:31 +02:00
parent 06de5f37d5
commit 1cbf00c02c
7 changed files with 113 additions and 135 deletions

View File

@@ -7,23 +7,29 @@ import com.example.architecture.core.domain.DataError
import com.example.architecture.core.domain.Result
import com.example.architecture.feature.characters.domain.CharacterRepository
import com.example.architecture.feature.characters.domain.model.Character
import com.example.architecture.feature.characters.domain.model.CharacterDetails
import com.example.architecture.feature.characters.domain.model.CharacterStatus
import com.example.architecture.feature.characters.domain.model.CharactersPage
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.mockk
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Test
/**
* Tests for the (thin pass-through) [GetCharactersPageUseCase]: it must forward the requested page to
* the repository and return its result verbatim — success and error alike. Pure JVM test on the
* JUnit 5 platform (see DomainModuleConventionPlugin); collaborator is a hand-written fake.
* JUnit 5 platform (see DomainModuleConventionPlugin); the [CharacterRepository] collaborator is a
* MockK mock, stubbed with `coEvery` and verified with `coVerify`.
*/
class GetCharactersPageUseCaseTest {
private val repository = mockk<CharacterRepository>()
private val useCase = GetCharactersPageUseCase(repository)
@Test
fun `returns the repository page on success`() = runBlocking {
val page = CharactersPage(characters = listOf(domainCharacter(1)), nextPage = 2)
val useCase = GetCharactersPageUseCase(FakeCharacterRepository(pageResult = Result.Success(page)))
coEvery { repository.getCharacters(1) } returns Result.Success(page)
val result = useCase(page = 1)
@@ -32,9 +38,7 @@ class GetCharactersPageUseCaseTest {
@Test
fun `propagates the repository error`() = runBlocking {
val useCase = GetCharactersPageUseCase(
FakeCharacterRepository(pageResult = Result.Error(DataError.Network.SERVER_ERROR)),
)
coEvery { repository.getCharacters(1) } returns Result.Error(DataError.Network.SERVER_ERROR)
val result = useCase(page = 1)
@@ -44,29 +48,12 @@ class GetCharactersPageUseCaseTest {
@Test
fun `forwards the requested page number`() = runBlocking {
val fake = FakeCharacterRepository(
pageResult = Result.Success(CharactersPage(characters = emptyList(), nextPage = null)),
)
val useCase = GetCharactersPageUseCase(fake)
coEvery { repository.getCharacters(any()) } returns
Result.Success(CharactersPage(characters = emptyList(), nextPage = null))
useCase(page = 7)
assertThat(fake.lastRequestedPage).isEqualTo(7)
}
private class FakeCharacterRepository(
private val pageResult: Result<CharactersPage, DataError>,
) : CharacterRepository {
var lastRequestedPage: Int? = null
private set
override suspend fun getCharacters(page: Int): Result<CharactersPage, DataError> {
lastRequestedPage = page
return pageResult
}
override suspend fun getCharacterDetails(id: Int): Result<CharacterDetails, DataError> =
Result.Error(DataError.Network.NOT_FOUND)
coVerify(exactly = 1) { repository.getCharacters(7) }
}
private fun domainCharacter(id: Int) = Character(