The files used in a blog post about unit testing.
sealed class PokemonListState { | |
object Loading : PokemonListState() | |
object Empty : PokemonListState() | |
class Loaded(val data: List<Pokemon>) : PokemonListState() | |
class Error(val error: Throwable?) : PokemonListState() | |
} |
class PokemonListViewModel( | |
private val repository: PokemonRepository | |
) { | |
private var state: PokemonListState? = null | |
val pokemon: List<Pokemon>? | |
get() = (state as? PokemonListState.Loaded)?.data | |
val showLoading: Boolean | |
get() = state is PokemonListState.Loading | |
val showError: Boolean | |
get() = state is PokemonListState.Error | |
val showData: Boolean | |
get() = state is PokemonListState.Loaded | |
val showEmptyState: Boolean | |
get() = state is PokemonListState.Empty | |
init { | |
fetchPokemonList() | |
} | |
private fun fetchPokemonList() { | |
state = PokemonListState.Loading | |
try { | |
val pokemonList = repository.getPokemon() | |
state = if (pokemonList.isEmpty()) { | |
PokemonListState.Empty | |
} else { | |
PokemonListState.Loaded(pokemonList) | |
} | |
} catch (error: Throwable) { | |
state = PokemonListState.Error(error) | |
} | |
} | |
} |
class PokemonListViewModelRobot { | |
private lateinit var viewModel: PokemonListViewModel | |
fun buildViewModel(repository: PokemonRepository): PokemonListViewModelRobot { | |
this.viewModel = PokemonListViewModel(repository) | |
return this | |
} | |
fun assertPokemonList(expectedPokemon: List<Pokemon>?): PokemonListViewModelRobot { | |
val actualPokemon = viewModel.pokemon | |
assertEquals(expectedPokemon, actualPokemon) | |
return this | |
} | |
fun assertShowLoading(expectedShowing: Boolean): PokemonListViewModelRobot { | |
val actualShowing = viewModel.showLoading | |
assertEquals(expectedShowing, actualShowing) | |
return this | |
} | |
fun assertShowData(expectedShowing: Boolean): PokemonListViewModelRobot { | |
val actualShowing = viewModel.showData | |
assertEquals(expectedShowing, actualShowing) | |
return this | |
} | |
fun assertShowError(expectedShowing: Boolean): PokemonListViewModelRobot { | |
val actualShowing = viewModel.showError | |
assertEquals(expectedShowing, actualShowing) | |
return this | |
} | |
fun assertShowEmptyState(expectedShowing: Boolean): PokemonListViewModelRobot { | |
val actualShowing = viewModel.showEmptyState | |
assertEquals(expectedShowing, actualShowing) | |
return this | |
} | |
} |
class PokemonListViewModelTest { | |
private lateinit var testRobot: PokemonListViewModelRobot | |
@Before | |
fun setUp() { | |
testRobot = PokemonListViewModelRobot() | |
} | |
@Test | |
fun successfulFetch() { | |
val expectedPokemon = listOf(Pokemon(name = "Squirtle")) | |
testRobot | |
.buildViewModel(repository = SuccessfulRepository()) | |
.assertPokemonList(expectedPokemon) | |
.assertShowData(true) | |
.assertShowError(false) | |
.assertShowLoading(false) | |
.assertShowEmptyState(false) | |
} | |
@Test | |
fun emptyFetch() { | |
testRobot | |
.buildViewModel(repository = EmptyRepository()) | |
.assertPokemonList(null) | |
.assertShowEmptyState(true) | |
.assertShowError(false) | |
.assertShowLoading(false) | |
.assertShowData(false) | |
} | |
@Test | |
fun errorFetch() { | |
testRobot | |
.buildViewModel(repository = ErrorRepository()) | |
.assertPokemonList(null) | |
.assertShowError(true) | |
.assertShowLoading(false) | |
.assertShowData(false) | |
.assertShowEmptyState(false) | |
} | |
} |
interface PokemonRepository { | |
fun getPokemon(): List<Pokemon> | |
} |
class SuccessfulRepository : PokemonRepository { | |
override fun getPokemon(): List<Pokemon> { | |
return listOf(Pokemon(name = "Squirtle")) | |
} | |
} | |
class EmptyRepository : PokemonRepository { | |
override fun getPokemon(): List<Pokemon> { | |
return emptyList() | |
} | |
} | |
class ErrorRepository : PokemonRepository { | |
override fun getPokemon(): List<Pokemon> { | |
throw Throwable("Whoops") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment