Usage of MockK's matcher any() instead of object type makes my unit test work. Why?

53 views Asked by At

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?

I'm using MockK + Turbine to test the flows.

0

There are 0 answers