简体   繁体   中英

Android testing view model with mockK

I'm trying to test my view model with mockK library. but i can not figure it out how to do that. This is my class. I have a use case and a repository:

    @ExperimentalCoroutinesApi
class MainViewModelTest {

    private val getRecentPhotosUseCase:GetRecentPhotosUseCase= mockk()
    private val recentPhotosRepository:RemoteRecentPhotosRepository= mockk()
    private val mainViewModel by lazy { RecentPhotosViewModel(getRecentPhotosUseCase) }
    @ExperimentalCoroutinesApi
    @get:Rule
    var mainCoroutineRule = MainCoroutineRule()

    @get:Rule
    var instantTaskExecutorRule = InstantTaskExecutorRule()

    @Before
    fun setupBefore(){
        startKoin {
            androidContext(App.getInstance())
            if (BuildConfig.DEBUG) androidLogger(Level.DEBUG)
            modules(appModules + domainModules + dataModules)
        }
    }

    @Test
    fun `get recent photo success`(){
         val map: MutableMap<String, String> = HashMap()
    map["format"] = "json"
    map["method"] = "flickr.photos.getRecent1"
    map["nojsoncallback"]="1"
    map["per_page"]="20"
    map["page"]= "1"
    val recentPhotoResponse = mockk<RecentPhotos>()
    //1- Mock calls
    every { runBlocking {recentPhotosRepository.getRecentPhotos(map)} } returns Success(recentPhotoResponse)
    mainViewModel.viewState.observeForever {  }
    runBlocking {mainViewModel.getRecentPhotos(map)}
    val getRecentPhotoSuccess= mainViewModel.viewState.value
    MatcherAssert.assertThat(
        "Received result [$getRecentPhotoSuccess] & mocked ${OnSuccess(recentPhotoResponse)} must be matches on each other!",
        getRecentPhotoSuccess,
        CoreMatchers.`is`(OnSuccess(recentPhotoResponse))
    )
    }
}

but when i run the test it gives me this error:

io.mockk.MockKException: no answer found for: GetRecentPhotosUseCase(#1).invoke({per_page=20, method=flickr.photos.getRecent1, format=json, page=1, nojsoncallback=1}, continuation {})

You need to tell mockk what the return value of getRecentPhotosUseCase.function(...) is. You do this like: every { mock.call(...) } returns Value . You can either put any() for the parameters, or you can use concrete values:

every { getRecentPhotosUseCase.function(any(), any(), ...) } returns YourResultValue
// or
every { getRecentPhotosUseCase.function(per_page = 20, ...) } returns YourResultValue

Alternatively if you do not wanna mock the result of GetRecentPhotosUseCase (maybe because it's irelevant for your test scenario) you use a relaxed mock :

A relaxed mock is the mock that returns some simple value for all functions. This allows to skip specifying behavior for each case, while still allowing to stub things you need. For reference types, chained mocks are returned.

val getRecentPhotosUseCase:GetRecentPhotosUseCase= mockk(relaxed = true)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM