I have the following unit testing class that tests if a flow comes alright from the usecase.
This test is passing as I want. The thing is that when I use normal parameters instead of any()
in the usecase invoke method the test doesn't pass. The flow weeklyWeatherUiState
is not being updated. Check the comment.
@RunWith(JUnit4::class)
@ExperimentalCoroutinesApi
class QuestionUnitTest {
@get:Rule
var instantExecutorRule = InstantTaskExecutorRule()
@MockK private lateinit var getCurrentWeatherUseCase: GetCurrentWeatherUseCase
@RelaxedMockK private lateinit var isImperialUseCase: IsImperialUseCase
@RelaxedMockK private lateinit var updateUnitMeasureUseCase: UpdateUnitMeasureUseCase
private lateinit var viewModel: WeatherViewModel
@Before
fun setUp() {
MockKAnnotations.init(this)
Dispatchers.setMain(StandardTestDispatcher())
viewModel = WeatherViewModel(
getCurrentWeatherUseCase,
isImperialUseCase,
updateUnitMeasureUseCase
)
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
@Test
fun `Question about any() matcher`() = runTest {
coEvery {
getCurrentWeatherUseCase.invoke(
city = any(),
isImperial = any(),
startDate = any()
)
// using the bellow instead of above, the code fails the test
// getCurrentWeatherUseCase.invoke(
// city = City("Sao Paulo"),
// isImperial = false,
// startDate = "2024-02-22"
// )
} returns flowOf(DataResponse.Success(listOf(Weather())))
viewModel.getWeeklyWeather(City("Sao Paulo"))
viewModel.weeklyWeatherUiState.test {
awaitItem() // UiState.Loading
val response = awaitItem()
assertTrue(response is UiState.Success)
cancelAndIgnoreRemainingEvents()
}
}
}
The ViewModel is like this:
private val _weeklyWeatherUiState = MutableStateFlow<UiState<List<Weather>>>(UiState.Loading)
val weeklyWeatherUiState: StateFlow<UiState<List<Weather>>> get() = _weeklyWeatherUiState
fun getWeeklyWeather(city: City) {
viewModelScope.launch {
getWeatherUseCase.invoke(city, isImperial(), getTodaysDate()).collect {
when (it) {
is DataResponse.Success -> {
_weeklyWeatherUiState.value = UiState.Success(it.data)
}
is DataResponse.Error -> {
_weeklyWeatherUiState.value = UiState.Error(it.message)
}
}
}
}
}
Why using the any() mockK's argument matcher works and using the expected objects doesn't?