Issue#11 Adjust SharedTests by using new TestDispatcher instead of deprecated TestDispatchers
This commit is contained in:
parent
46d9263742
commit
8ae94cfe92
4 changed files with 89 additions and 33 deletions
|
|
@ -1,7 +1,10 @@
|
|||
package org.fnives.test.showcase.testutils.configuration
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.test.TestCoroutineDispatcher
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestCoroutineScheduler
|
||||
import kotlinx.coroutines.test.TestDispatcher
|
||||
import kotlinx.coroutines.test.resetMain
|
||||
import kotlinx.coroutines.test.setMain
|
||||
import org.fnives.test.showcase.storage.database.DatabaseInitialization
|
||||
|
|
@ -9,16 +12,16 @@ import org.fnives.test.showcase.testutils.idling.advanceUntilIdleWithIdlingResou
|
|||
import org.junit.runner.Description
|
||||
import org.junit.runners.model.Statement
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class TestCoroutineMainDispatcherTestRule : MainDispatcherTestRule {
|
||||
|
||||
private lateinit var testDispatcher: TestCoroutineDispatcher
|
||||
private lateinit var testDispatcher: TestDispatcher
|
||||
|
||||
override fun apply(base: Statement, description: Description): Statement =
|
||||
object : Statement() {
|
||||
@Throws(Throwable::class)
|
||||
override fun evaluate() {
|
||||
val dispatcher = TestCoroutineDispatcher()
|
||||
dispatcher.pauseDispatcher()
|
||||
val dispatcher = StandardTestDispatcher(TestCoroutineScheduler())
|
||||
Dispatchers.setMain(dispatcher)
|
||||
testDispatcher = dispatcher
|
||||
DatabaseInitialization.dispatcher = dispatcher
|
||||
|
|
@ -39,10 +42,10 @@ class TestCoroutineMainDispatcherTestRule : MainDispatcherTestRule {
|
|||
}
|
||||
|
||||
override fun advanceUntilIdle() {
|
||||
testDispatcher.advanceUntilIdle()
|
||||
testDispatcher.scheduler.advanceUntilIdle()
|
||||
}
|
||||
|
||||
override fun advanceTimeBy(delayInMillis: Long) {
|
||||
testDispatcher.advanceTimeBy(delayInMillis)
|
||||
testDispatcher.scheduler.advanceTimeBy(delayInMillis)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,15 +4,11 @@ import androidx.test.espresso.Espresso
|
|||
import androidx.test.espresso.IdlingRegistry
|
||||
import androidx.test.espresso.IdlingResource
|
||||
import androidx.test.espresso.matcher.ViewMatchers
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.TestCoroutineDispatcher
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.TestDispatcher
|
||||
import org.fnives.test.showcase.testutils.viewactions.LoopMainThreadFor
|
||||
import org.fnives.test.showcase.testutils.viewactions.LoopMainThreadUntilIdle
|
||||
|
||||
private val idleScope = CoroutineScope(Dispatchers.IO)
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
// workaround, issue with idlingResources is tracked here https://github.com/robolectric/robolectric/issues/4807
|
||||
fun anyResourceIdling(): Boolean = !IdlingRegistry.getInstance().resources.all(IdlingResource::isIdleNow)
|
||||
|
|
@ -21,13 +17,14 @@ fun awaitIdlingResources() {
|
|||
val idlingRegistry = IdlingRegistry.getInstance()
|
||||
if (idlingRegistry.resources.all(IdlingResource::isIdleNow)) return
|
||||
|
||||
val executor = Executors.newSingleThreadExecutor()
|
||||
var isIdle = false
|
||||
idleScope.launch {
|
||||
executor.submit {
|
||||
do {
|
||||
idlingRegistry.resources
|
||||
.filterNot(IdlingResource::isIdleNow)
|
||||
.forEach { idlingRegistry ->
|
||||
idlingRegistry.awaitUntilIdle()
|
||||
.forEach { idlingResource ->
|
||||
idlingResource.awaitUntilIdle()
|
||||
}
|
||||
} while (!idlingRegistry.resources.all(IdlingResource::isIdleNow))
|
||||
isIdle = true
|
||||
|
|
@ -35,23 +32,25 @@ fun awaitIdlingResources() {
|
|||
while (!isIdle) {
|
||||
loopMainThreadFor(200L)
|
||||
}
|
||||
executor.shutdown()
|
||||
}
|
||||
|
||||
private suspend fun IdlingResource.awaitUntilIdle() {
|
||||
private fun IdlingResource.awaitUntilIdle() {
|
||||
// using loop because some times, registerIdleTransitionCallback wasn't called
|
||||
while (true) {
|
||||
if (isIdleNow) return
|
||||
delay(100)
|
||||
Thread.sleep(100L)
|
||||
}
|
||||
}
|
||||
|
||||
fun TestCoroutineDispatcher.advanceUntilIdleWithIdlingResources() {
|
||||
advanceUntilIdle() // advance until a request is sent
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
fun TestDispatcher.advanceUntilIdleWithIdlingResources() {
|
||||
scheduler.advanceUntilIdle() // advance until a request is sent
|
||||
while (anyResourceIdling()) { // check if any request is in progress
|
||||
awaitIdlingResources() // complete all requests and other idling resources
|
||||
advanceUntilIdle() // run coroutines after request is finished
|
||||
scheduler.advanceUntilIdle() // run coroutines after request is finished
|
||||
}
|
||||
advanceUntilIdle()
|
||||
scheduler.advanceUntilIdle()
|
||||
}
|
||||
|
||||
fun loopMainThreadUntilIdleWithIdlingResources() {
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class SplashActivityTest : KoinTest {
|
|||
|
||||
activityScenario = ActivityScenario.launch(HiltSplashActivity::class.java)
|
||||
|
||||
mainDispatcherTestRule.advanceTimeBy(500)
|
||||
mainDispatcherTestRule.advanceTimeBy(501)
|
||||
|
||||
splashRobot.assertHomeIsStarted()
|
||||
.assertAuthIsNotStarted()
|
||||
|
|
@ -93,9 +93,36 @@ class SplashActivityTest : KoinTest {
|
|||
|
||||
activityScenario = ActivityScenario.launch(HiltSplashActivity::class.java)
|
||||
|
||||
mainDispatcherTestRule.advanceTimeBy(500)
|
||||
mainDispatcherTestRule.advanceTimeBy(501)
|
||||
|
||||
splashRobot.assertAuthIsStarted()
|
||||
.assertHomeIsNotStarted()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun loggedOutStatesNotEnoughTime() {
|
||||
setupLoggedInState.setupLogout()
|
||||
|
||||
activityScenario = ActivityScenario.launch(HiltSplashActivity::class.java)
|
||||
|
||||
mainDispatcherTestRule.advanceTimeBy(10)
|
||||
|
||||
splashRobot.assertAuthIsNotStarted()
|
||||
.assertHomeIsNotStarted()
|
||||
}
|
||||
|
||||
/** GIVEN loggedInState and not enough time WHEN opened THEN no activity is started */
|
||||
@Test
|
||||
fun loggedInStatesNotEnoughTime() {
|
||||
setupLoggedInState.setupLogin(mockServerScenarioSetupTestRule.mockServerScenarioSetup)
|
||||
|
||||
activityScenario = ActivityScenario.launch(HiltSplashActivity::class.java)
|
||||
|
||||
mainDispatcherTestRule.advanceTimeBy(10)
|
||||
|
||||
splashRobot.assertHomeIsNotStarted()
|
||||
.assertAuthIsNotStarted()
|
||||
|
||||
setupLoggedInState.setupLogout()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package org.fnives.test.showcase.ui.splash
|
||||
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
|
@ -26,10 +25,6 @@ class SplashActivityTest : KoinTest {
|
|||
|
||||
private val splashRobot: SplashRobot get() = robotTestRule.robot
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
val instantTaskExecutorRule = InstantTaskExecutorRule()
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
val robotTestRule = RobotTestRule(SplashRobot())
|
||||
|
|
@ -61,14 +56,15 @@ class SplashActivityTest : KoinTest {
|
|||
disposable.dispose()
|
||||
}
|
||||
|
||||
/** GIVEN loggedInState WHEN opened THEN MainActivity is started */
|
||||
/** GIVEN loggedInState WHEN opened after some time THEN MainActivity is started */
|
||||
@Test
|
||||
fun loggedInStateNavigatesToHome() {
|
||||
SetupLoggedInState.setupLogin(mockServerScenarioSetupTestRule.mockServerScenarioSetup)
|
||||
|
||||
activityScenario = ActivityScenario.launch(SplashActivity::class.java)
|
||||
activityScenario.moveToState(Lifecycle.State.RESUMED)
|
||||
|
||||
mainDispatcherTestRule.advanceTimeBy(500)
|
||||
mainDispatcherTestRule.advanceTimeBy(501)
|
||||
|
||||
splashRobot.assertHomeIsStarted()
|
||||
.assertAuthIsNotStarted()
|
||||
|
|
@ -76,16 +72,47 @@ class SplashActivityTest : KoinTest {
|
|||
SetupLoggedInState.setupLogout()
|
||||
}
|
||||
|
||||
/** GIVEN loggedOffState WHEN opened THEN AuthActivity is started */
|
||||
/** GIVEN loggedOffState WHEN opened after some time THEN AuthActivity is started */
|
||||
@Test
|
||||
fun loggedOutStatesNavigatesToAuthentication() {
|
||||
SetupLoggedInState.setupLogout()
|
||||
|
||||
activityScenario = ActivityScenario.launch(SplashActivity::class.java)
|
||||
activityScenario.moveToState(Lifecycle.State.RESUMED)
|
||||
|
||||
mainDispatcherTestRule.advanceTimeBy(500)
|
||||
mainDispatcherTestRule.advanceTimeBy(501)
|
||||
|
||||
splashRobot.assertAuthIsStarted()
|
||||
.assertHomeIsNotStarted()
|
||||
}
|
||||
|
||||
/** GIVEN loggedOffState and not enough time WHEN opened THEN no activity is started */
|
||||
@Test
|
||||
fun loggedOutStatesNotEnoughTime() {
|
||||
SetupLoggedInState.setupLogout()
|
||||
|
||||
activityScenario = ActivityScenario.launch(SplashActivity::class.java)
|
||||
activityScenario.moveToState(Lifecycle.State.RESUMED)
|
||||
|
||||
mainDispatcherTestRule.advanceTimeBy(10)
|
||||
|
||||
splashRobot.assertAuthIsNotStarted()
|
||||
.assertHomeIsNotStarted()
|
||||
}
|
||||
|
||||
/** GIVEN loggedInState and not enough time WHEN opened THEN no activity is started */
|
||||
@Test
|
||||
fun loggedInStatesNotEnoughTime() {
|
||||
SetupLoggedInState.setupLogin(mockServerScenarioSetupTestRule.mockServerScenarioSetup)
|
||||
|
||||
activityScenario = ActivityScenario.launch(SplashActivity::class.java)
|
||||
activityScenario.moveToState(Lifecycle.State.RESUMED)
|
||||
|
||||
mainDispatcherTestRule.advanceTimeBy(10)
|
||||
|
||||
splashRobot.assertHomeIsNotStarted()
|
||||
.assertAuthIsNotStarted()
|
||||
|
||||
SetupLoggedInState.setupLogout()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue