【发布时间】:2021-08-27 15:16:13
【问题描述】:
我正在尝试为我的 viewModel 编写一个单元测试,但我还没有弄清楚如何去做。我正在使用 kotlin flow 和 jetpack compose。在 viewModel 中,该函数更改了 mutableState 列表的值,但是当我在测试中调用它时,我不知道如何检索该值。
下面是我的视图模型、存储库、假存储库和我到目前为止的测试。 我该怎么做?
@HiltViewModel
class MarvelViewModel @Inject constructor(
private val repository: MarvelRepository
) : ViewModel() {
val result: MutableState<List<Result>> = mutableStateOf(listOf())
fun searchCharacter(
name: String,
context: Context
) {
viewModelScope.launch {
val ts = System.currentTimeMillis().toString()
val md = MessageDigest.getInstance("MD5")
val input = ts + PRIVATE_KEY + PUBLIC_KEY
val hash = BigInteger(1, md.digest(input.toByteArray())).toString(16)
val offset = if (page.value == 1) 0 else PAGE_SIZE * page.value
repository.searchCharacter(
name = name,
limit = PAGE_SIZE,
offset = offset,
ts = ts,
apikey = PUBLIC_KEY,
hash = hash
).onEach { dataState ->
loading.value = dataState.loading
dataState.data?.let {
Log.d(DEBUG_TAG, it.toString())
if (it.data.total > PAGE_SIZE) {
val rest = it.data.total % PAGE_SIZE
numPages.value = (it.data.total + rest) / PAGE_SIZE
}
nameSearch.value = textSearch.value
result.value = it.data.results
pageNumberList.value = (1..numPages.value).toList()
}
dataState.error?.let {
Toast.makeText(context, "Falha ao carregar", Toast.LENGTH_SHORT).show()
}
}.launchIn(viewModelScope)
}
}
class MarvelRepositoryImpl @Inject constructor(
private val retrofitService: RetrofitService
) : MarvelRepository {
override suspend fun searchCharacter(
name: String,
limit: Int,
offset: Int,
ts: String,
apikey: String,
hash: String
): Flow<DataState<Response>> = flow {
try {
emit(DataState.loading())
val response = retrofitService.search(name, limit, offset, ts, apikey, hash)
emit(DataState.success(response))
} catch (e: Exception) {
emit(DataState.error<Response>(e.message ?: "Unknown Error"))
}
}
}
class FakeRepositoryImpl : MarvelRepository {
override suspend fun searchCharacter(
name: String,
limit: Int,
offset: Int,
ts: String,
apikey: String,
hash: String
): Flow<DataState<Response>> = flow {
emit(DataState.loading())
emit(DataState.success(response))
}
}
val response = Response(
data = Data(
count = 4, limit = 4, offset = 0, results = listOf(
Result(
description = "Wounded", id = 1009368, name = "Iron Man",
thumbnail = Thumbnail(
extension = "jpg",
path = "http://i.annihil.us/u/prod/marvel/i/mg/9/c0/527bb7b37ff55"
)
),
Result(
description = "", id = 1017320, name = "Iron Man (Iron Man 3 - The Official Game)",
thumbnail = Thumbnail(
extension = "jpg",
path = "http://i.annihil.us/u/prod/marvel/i/mg/9/03/5239c1408c936"
)
),
Result(
description = "", id = 1017294, name = "Iron Man (LEGO Marvel Super Heroes)",
thumbnail = Thumbnail(
extension = "jpg",
path = "http://i.annihil.us/u/prod/marvel/i/mg/6/90/5239c3cc8a259"
)
),
Result(
description = "", id = 1017310, name = "Iron Man (Marvel Heroes)",
thumbnail = Thumbnail(
extension = "jpg",
path = "http://i.annihil.us/u/prod/marvel/i/mg/9/40/5239be60a67da"
)
)
), total = 7
), status = "Ok"
)
@ExperimentalCoroutinesApi
class MarvelViewModelTest {
@get:Rule
var instantExecutorRule = InstantTaskExecutorRule()
@get:Rule
var mainCoroutineRule = MainCoroutineRule()
val context = mock(Context::class.java)
private lateinit var viewModel: MarvelViewModel
private lateinit var repository: FakeRepositoryImpl
@Before
fun setup(){
repository = FakeRepositoryImpl()
viewModel = MarvelViewModel(repository)
}
@Test
fun `should return a flow of response`() = runBlockingTest {
viewModel.searchCharacter("iron man", context)
}
}
【问题讨论】:
-
你的测试完成了吗?
标签: android unit-testing kotlin android-jetpack-compose