Solution 1 :
It depends what is in your TestCoroutineRule
class, but one thing you should definitely do is inject a TestDispatcher
into your presenter, in place of both Dispatchers.Main and Dispatchers.IO.
Problem :
I know this has been asked a number of different ways with a number of different answers but none I can see help my situation. I am trying to test a presenter using coroutines. In order to verify behaviour I have implemented com.nhaarman.mockitokotlin2.mock
. All tests pass individually but when run together they fail randomly (2 pass, 1 pass, 3 pass etc.)
I don’t have that much experience with coroutines so I’m hoping someone with a bit more experience could steer me here. Below is my test class. I can add more info if required
package com.project.ui.search.results
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.never
import com.nhaarman.mockitokotlin2.whenever
import ie.distilledsch.dschapi.models.search.SavedSearchCreateResponse
import io.reactivex.schedulers.TestScheduler
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.ArgumentMatchers
import org.mockito.Mock
import org.mockito.Mockito.doThrow
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import retrofit2.HttpException
@ExperimentalCoroutinesApi
class SPSearchResultsPresenterSavedSearchesTest {
@get:Rule val testCoroutineRule = TestCoroutineRule()
private lateinit var interactor: SPSearchResultsInteractor
@Mock private lateinit var view: SPSearchResultsView
@Mock private lateinit var context: Context
@Mock private lateinit var interactorBtwAdListAndAdDetails: InteractorBetweenListOfAdsAndAdDetails
@Mock private lateinit var daftLoginManager: DaftLoginManager
private lateinit var searchForm: SearchForm
private lateinit var searchManager: SearchManager
private lateinit var testScheduler: TestScheduler
lateinit var presenter: SPSearchResultsPresenter
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
interactor = mock()
testScheduler = TestScheduler()
searchForm = SearchForm()
searchManager = SearchManager(searchForm)
val presenterToTest = SPSearchResultsPresenterImpl(testScheduler, testScheduler,
testScheduler, Dispatchers.Main, Dispatchers.IO, interactorBtwAdListAndAdDetails, daftLoginManager, context, view)
presenterToTest.interactor = interactor
presenterToTest.searchManager = searchManager
presenter = presenterToTest
}
@Test
fun `save search dialog confirm click success`() = runBlocking {
val savedSearchTitle = "title"
val savedSearchID = 1234
val responseModel = SavedSearchCreateResponse(201, "Created", savedSearchID)
whenever(interactor.saveNewSearch(savedSearchTitle)).thenReturn(responseModel)
presenter.onSaveSearchDialogOkClick(savedSearchTitle)
verify(interactor).saveNewSearch(savedSearchTitle)
verify(view).displayIconForSavedSearch()
}
@Test
fun `save search dialog confirm click failure`() = runBlocking {
val savedSearchTitle = "title"
val exception :HttpException = mock()
doThrow(exception).`when`(interactor).saveNewSearch(savedSearchTitle)
presenter.onSaveSearchDialogOkClick(savedSearchTitle)
verify(interactor).saveNewSearch(savedSearchTitle)
verify(view, never()).displayIconForSavedSearch()
verify(view).showFetchSavedSearchFailedToast()
}
@Test
fun `delete search success logged in`() = runBlocking {
val savedSearchID = 1234
whenever(interactor.isUserLoggedIn()).thenReturn(true)
searchManager.isSearchSaved = true
searchManager.savedSearchId = savedSearchID
presenter.onSaveMenuItemClick()
verify(interactor).deleteSavedSearch(savedSearchID)
verify(view).displayIconForUnsavedSearch()
}
@Test
fun `delete search error logged in`() = runBlocking {
val savedSearchID = 1234
val exception :HttpException = mock()
whenever(interactor.isUserLoggedIn()).thenReturn(true)
searchManager.isSearchSaved = true
searchManager.savedSearchId = savedSearchID
whenever(interactor.deleteSavedSearch(savedSearchID)).thenThrow(exception)
presenter.onSaveMenuItemClick()
verify(interactor).deleteSavedSearch(savedSearchID)
verify(view, never()).displayIconForUnsavedSearch()
verify(view).showSnackBar(ArgumentMatchers.anyInt())
}
@Test
fun `click on save search not logged in` () = runBlocking {
whenever(interactor.isUserLoggedIn()).thenReturn(false)
presenter.onSaveMenuItemClick()
verify(view).showLoginScreen()
}
}
Comments
Comment posted by ibrahimyilmaz
TestCorotuneRule