[英]Android Studio Coroutine Tests Passing individually, failing when run together
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
.为了验证行为,我实现
com.nhaarman.mockitokotlin2.mock
。 All tests pass individually but when run together they fail randomly (2 pass, 1 pass, 3 pass etc.)所有测试都单独通过,但一起运行时它们随机失败(2 次通过、1 次通过、3 次通过等)
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.
下面是我的测试 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()
}
}
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.这取决于您的
TestCoroutineRule
class 中的内容,但是您绝对应该做的一件事是将TestDispatcher
注入您的演示者,以代替 Dispatchers.Main 和 Dispatchers.IO。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.