2

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 {})
Shadman Adman
  • 383
  • 3
  • 12

1 Answers1

2

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)
ChristianB
  • 2,452
  • 2
  • 10
  • 22
  • Thanks man. your solution worked. but i don't know why Assert is fail.both OnSuccess class are the same but the @number is different and i don't undrestand. I updated my question. – Shadman Adman Jan 10 '21 at 16:42
  • 2
    You are welcome. But I suggest you revert your update and you ask a new question. Because if other people reading this (updated) question, this answer does not match the question anymore. You can write a comment with a lint to your new question. – ChristianB Jan 10 '21 at 17:26