Issue#13 Simplify rule sets to minimal and appy them in order

This commit is contained in:
Gergely Hegedus 2022-01-27 00:09:36 +02:00
parent d8b9fadcbc
commit 5a08525e42
10 changed files with 140 additions and 157 deletions

View file

@ -4,7 +4,9 @@ import okhttp3.OkHttpClient
import okhttp3.tls.HandshakeCertificates
import org.fnives.test.showcase.model.network.BaseUrl
import org.fnives.test.showcase.network.mockserver.MockServerScenarioSetup
import org.fnives.test.showcase.testutils.idling.NetworkSynchronization.OkHttpClientTypes
import org.fnives.test.showcase.testutils.idling.NetworkSynchronizationTestRule
import org.fnives.test.showcase.testutils.idling.NetworkSynchronizationTestRule.OkHttpClientTypes
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
import org.koin.core.context.loadKoinModules
@ -12,14 +14,26 @@ import org.koin.dsl.module
import org.koin.test.KoinTest
import org.koin.test.get
class MockServerScenarioSetupTestRule : ReloadKoinModulesIfNecessaryTestRule(), KoinTest {
/**
* TestRule which ensures Koin is reseted between each tests and setups Network mocking.
*
* It First resets koin if needed.
* Then creates and starts the mockwebserver, it also injects the correct baseUrl into the OkHttp Client.
* Then synchronizes Espresso with the OkHttp Client
*/
class MockServerScenarioSetupResetingTestRule(
private val reloadKoinModulesIfNecessaryTestRule: ReloadKoinModulesIfNecessaryTestRule = ReloadKoinModulesIfNecessaryTestRule(),
private val networkSynchronizationTestRule: NetworkSynchronizationTestRule = NetworkSynchronizationTestRule()
) : TestRule, KoinTest {
lateinit var mockServerScenarioSetup: MockServerScenarioSetup
private val sessionlessQualifier get() = OkHttpClientTypes.SESSIONLESS.asQualifier()
override fun apply(base: Statement, description: Description): Statement =
super.apply(createStatement(base), description)
networkSynchronizationTestRule.apply(base, description)
.let(::createStatement)
.let { reloadKoinModulesIfNecessaryTestRule.apply(it, description) }
private fun createStatement(base: Statement) = object : Statement() {
@Throws(Throwable::class)

View file

@ -9,6 +9,7 @@ import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.GlobalContext
import org.koin.core.context.startKoin
import org.koin.core.context.stopKoin
import org.koin.mp.KoinPlatformTools
@ -22,7 +23,7 @@ import org.koin.test.KoinTest
*
* Note: Do not use if you want your test's to share Koin, and in such case do not stop your Koin.
*/
open class ReloadKoinModulesIfNecessaryTestRule : TestRule, KoinTest {
class ReloadKoinModulesIfNecessaryTestRule : TestRule, KoinTest {
override fun apply(base: Statement, description: Description): Statement =
ReinitKoinStatement(base)
@ -38,6 +39,7 @@ open class ReloadKoinModulesIfNecessaryTestRule : TestRule, KoinTest {
private fun reinitKoinIfNeeded() {
if (KoinPlatformTools.defaultContext().getOrNull() != null) return
if (GlobalContext.getOrNull() != null) return
val application = ApplicationProvider.getApplicationContext<TestShowcaseApplication>()
val baseUrl = BaseUrl(BuildConfig.BASE_URL)

View file

@ -12,3 +12,7 @@ interface MainDispatcherTestRule : TestRule {
fun advanceTimeBy(delayInMillis: Long)
}
@Suppress("TestFunctionName")
fun MainDispatcherTestRule(): MainDispatcherTestRule =
SpecificTestConfigurationsFactory.createMainDispatcherTestRule()

View file

@ -3,14 +3,35 @@ package org.fnives.test.showcase.testutils.idling
import androidx.annotation.CheckResult
import androidx.test.espresso.IdlingResource
import okhttp3.OkHttpClient
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
import org.koin.core.qualifier.StringQualifier
import org.koin.test.KoinTest
import org.koin.test.get
object NetworkSynchronization : KoinTest {
class NetworkSynchronizationTestRule : TestRule, KoinTest {
private var disposable: Disposable? = null
override fun apply(base: Statement, description: Description): Statement {
return object : Statement() {
override fun evaluate() {
disposable = registerNetworkingSynchronization()
try {
base.evaluate()
} finally {
dispose()
}
}
}
}
fun dispose() = disposable?.dispose()
@CheckResult
fun registerNetworkingSynchronization(): Disposable {
private fun registerNetworkingSynchronization(): Disposable {
val idlingResources = OkHttpClientTypes.values()
.map { it to getOkHttpClient(it) }
.associateBy { it.second.dispatcher }

View file

@ -2,6 +2,8 @@ package org.fnives.test.showcase.testutils.statesetup
import androidx.lifecycle.Lifecycle
import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.intent.Intents
import androidx.test.runner.intent.IntentStubberRegistry
import org.fnives.test.showcase.network.mockserver.MockServerScenarioSetup
import org.fnives.test.showcase.network.mockserver.scenario.auth.AuthScenario
import org.fnives.test.showcase.testutils.configuration.MainDispatcherTestRule
@ -15,7 +17,8 @@ object SetupAuthenticationState : KoinTest {
fun setupLogin(
mainDispatcherTestRule: MainDispatcherTestRule,
mockServerScenarioSetup: MockServerScenarioSetup
mockServerScenarioSetup: MockServerScenarioSetup,
resetIntents: Boolean = true
) {
mockServerScenarioSetup.setScenario(AuthScenario.Success(username = "a", password = "b"))
val activityScenario = ActivityScenario.launch(AuthActivity::class.java)
@ -30,19 +33,27 @@ object SetupAuthenticationState : KoinTest {
mainDispatcherTestRule.advanceUntilIdleOrActivityIsDestroyed()
activityScenario.close()
resetIntentsIfNeeded(resetIntents)
}
fun setupLogout(
mainDispatcherTestRule: MainDispatcherTestRule
mainDispatcherTestRule: MainDispatcherTestRule,
resetIntents: Boolean = true
) {
val activityScenario = ActivityScenario.launch(MainActivity::class.java)
activityScenario.moveToState(Lifecycle.State.RESUMED)
val homeRobot = HomeRobot()
homeRobot
.clickSignOut()
HomeRobot().clickSignOut()
mainDispatcherTestRule.advanceUntilIdleOrActivityIsDestroyed()
activityScenario.close()
resetIntentsIfNeeded(resetIntents)
}
private fun resetIntentsIfNeeded(resetIntents: Boolean) {
if (resetIntents && IntentStubberRegistry.isLoaded()) {
Intents.release()
Intents.init()
}
}
}

View file

@ -19,10 +19,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withText
import org.fnives.test.showcase.R
import org.fnives.test.showcase.model.content.Content
import org.fnives.test.showcase.model.content.FavouriteContent
import org.fnives.test.showcase.network.mockserver.MockServerScenarioSetup
import org.fnives.test.showcase.testutils.configuration.MainDispatcherTestRule
import org.fnives.test.showcase.testutils.robot.Robot
import org.fnives.test.showcase.testutils.statesetup.SetupAuthenticationState
import org.fnives.test.showcase.testutils.viewactions.PullToRefresh
import org.fnives.test.showcase.testutils.viewactions.WithDrawable
import org.fnives.test.showcase.testutils.viewactions.notIntended
@ -33,8 +30,6 @@ class HomeRobot : Robot {
override fun init() {
Intents.init()
Intents.intending(IntentMatchers.hasComponent(AuthActivity::class.java.canonicalName))
.respondWith(Instrumentation.ActivityResult(0, null))
}
override fun release() {
@ -50,6 +45,9 @@ class HomeRobot : Robot {
}
fun clickSignOut() = apply {
Intents.intending(IntentMatchers.hasComponent(AuthActivity::class.java.canonicalName))
.respondWith(Instrumentation.ActivityResult(0, null))
Espresso.onView(withId(R.id.logout_cta)).perform(click())
}
@ -103,11 +101,4 @@ class HomeRobot : Robot {
Espresso.onView(withId(R.id.error_message))
.check(matches(allOf(isDisplayed(), withText(R.string.something_went_wrong))))
}
fun setupLogin(
mainDispatcherTestRule: MainDispatcherTestRule,
mockServerScenarioSetup: MockServerScenarioSetup
) {
SetupAuthenticationState.setupLogin(mainDispatcherTestRule, mockServerScenarioSetup)
}
}

View file

@ -6,17 +6,17 @@ import org.fnives.test.showcase.model.content.FavouriteContent
import org.fnives.test.showcase.network.mockserver.ContentData
import org.fnives.test.showcase.network.mockserver.scenario.content.ContentScenario
import org.fnives.test.showcase.network.mockserver.scenario.refresh.RefreshTokenScenario
import org.fnives.test.showcase.testutils.MockServerScenarioSetupTestRule
import org.fnives.test.showcase.testutils.configuration.SpecificTestConfigurationsFactory
import org.fnives.test.showcase.testutils.idling.Disposable
import org.fnives.test.showcase.testutils.idling.NetworkSynchronization
import org.fnives.test.showcase.testutils.MockServerScenarioSetupResetingTestRule
import org.fnives.test.showcase.testutils.configuration.MainDispatcherTestRule
import org.fnives.test.showcase.testutils.idling.loopMainThreadFor
import org.fnives.test.showcase.testutils.idling.loopMainThreadUntilIdleWithIdlingResources
import org.fnives.test.showcase.testutils.robot.RobotTestRule
import org.fnives.test.showcase.testutils.statesetup.SetupAuthenticationState.setupLogin
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import org.junit.runner.RunWith
import org.koin.test.KoinTest
@ -26,37 +26,26 @@ class MainActivityTest : KoinTest {
private lateinit var activityScenario: ActivityScenario<MainActivity>
@Rule
@JvmField
val robotRule = RobotTestRule(HomeRobot())
private val homeRobot get() = robotRule.robot
private val mockServerScenarioSetupTestRule = MockServerScenarioSetupResetingTestRule()
private val mockServerScenarioSetup
get() = mockServerScenarioSetupTestRule.mockServerScenarioSetup
private val mainDispatcherTestRule = MainDispatcherTestRule()
private val robot = HomeRobot()
@Rule
@JvmField
val mockServerScenarioSetupTestRule = MockServerScenarioSetupTestRule()
val mockServerScenarioSetup get() = mockServerScenarioSetupTestRule.mockServerScenarioSetup
@Rule
@JvmField
val mainDispatcherTestRule = SpecificTestConfigurationsFactory.createMainDispatcherTestRule()
private lateinit var disposable: Disposable
val ruleOrder: RuleChain = RuleChain.outerRule(mockServerScenarioSetupTestRule)
.around(mainDispatcherTestRule)
.around(RobotTestRule(robot))
@Before
fun setUp() {
disposable = NetworkSynchronization.registerNetworkingSynchronization()
homeRobot.setupLogin(
mainDispatcherTestRule,
mockServerScenarioSetup
)
fun setup() {
setupLogin(mainDispatcherTestRule, mockServerScenarioSetup)
}
@After
fun tearDown() {
activityScenario.close()
disposable.dispose()
}
/** GIVEN initialized MainActivity WHEN signout is clicked THEN user is signed out */
@ -66,10 +55,10 @@ class MainActivityTest : KoinTest {
activityScenario = ActivityScenario.launch(MainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.clickSignOut()
robot.clickSignOut()
mainDispatcherTestRule.advanceUntilIdleOrActivityIsDestroyed()
homeRobot.assertNavigatedToAuth()
robot.assertNavigatedToAuth()
}
/** GIVEN success response WHEN data is returned THEN it is shown on the ui */
@ -80,9 +69,9 @@ class MainActivityTest : KoinTest {
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
ContentData.contentSuccess.forEachIndexed { index, content ->
homeRobot.assertContainsItem(index, FavouriteContent(content, false))
robot.assertContainsItem(index, FavouriteContent(content, false))
}
homeRobot.assertDidNotNavigateToAuth()
robot.assertDidNotNavigateToAuth()
}
/** GIVEN success response WHEN item is clicked THEN ui is updated */
@ -92,11 +81,11 @@ class MainActivityTest : KoinTest {
activityScenario = ActivityScenario.launch(MainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.clickOnContentItem(0, ContentData.contentSuccess.first())
robot.clickOnContentItem(0, ContentData.contentSuccess.first())
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), true)
homeRobot.assertContainsItem(0, expectedItem)
robot.assertContainsItem(0, expectedItem)
.assertDidNotNavigateToAuth()
}
@ -107,7 +96,7 @@ class MainActivityTest : KoinTest {
activityScenario = ActivityScenario.launch(MainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.clickOnContentItem(0, ContentData.contentSuccess.first())
robot.clickOnContentItem(0, ContentData.contentSuccess.first())
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), true)
@ -116,7 +105,7 @@ class MainActivityTest : KoinTest {
activityScenario = ActivityScenario.launch(MainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.assertContainsItem(0, expectedItem)
robot.assertContainsItem(0, expectedItem)
.assertDidNotNavigateToAuth()
}
@ -127,13 +116,13 @@ class MainActivityTest : KoinTest {
activityScenario = ActivityScenario.launch(MainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.clickOnContentItem(0, ContentData.contentSuccess.first())
robot.clickOnContentItem(0, ContentData.contentSuccess.first())
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.clickOnContentItem(0, ContentData.contentSuccess.first())
robot.clickOnContentItem(0, ContentData.contentSuccess.first())
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), false)
homeRobot.assertContainsItem(0, expectedItem)
robot.assertContainsItem(0, expectedItem)
.assertDidNotNavigateToAuth()
}
@ -144,7 +133,7 @@ class MainActivityTest : KoinTest {
activityScenario = ActivityScenario.launch(MainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.assertContainsNoItems()
robot.assertContainsNoItems()
.assertContainsError()
.assertDidNotNavigateToAuth()
}
@ -159,14 +148,14 @@ class MainActivityTest : KoinTest {
activityScenario = ActivityScenario.launch(MainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.swipeRefresh()
robot.swipeRefresh()
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
loopMainThreadFor(2000L)
ContentData.contentSuccess.forEachIndexed { index, content ->
homeRobot.assertContainsItem(index, FavouriteContent(content, false))
robot.assertContainsItem(index, FavouriteContent(content, false))
}
homeRobot.assertDidNotNavigateToAuth()
robot.assertDidNotNavigateToAuth()
}
/** GIVEN success then error WHEN retried THEN error is shown */
@ -179,13 +168,13 @@ class MainActivityTest : KoinTest {
activityScenario = ActivityScenario.launch(MainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.swipeRefresh()
robot.swipeRefresh()
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
loopMainThreadUntilIdleWithIdlingResources()
mainDispatcherTestRule.advanceTimeBy(1000L)
loopMainThreadFor(1000)
homeRobot
robot
.assertContainsError()
.assertContainsNoItems()
.assertDidNotNavigateToAuth()
@ -204,9 +193,9 @@ class MainActivityTest : KoinTest {
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
ContentData.contentSuccess.forEachIndexed { index, content ->
homeRobot.assertContainsItem(index, FavouriteContent(content, false))
robot.assertContainsItem(index, FavouriteContent(content, false))
}
homeRobot.assertDidNotNavigateToAuth()
robot.assertDidNotNavigateToAuth()
}
/** GIVEN unauthenticated then error WHEN loaded THEN navigated to auth */
@ -218,6 +207,6 @@ class MainActivityTest : KoinTest {
activityScenario = ActivityScenario.launch(MainActivity::class.java)
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
homeRobot.assertNavigatedToAuth()
robot.assertNavigatedToAuth()
}
}

View file

@ -4,16 +4,14 @@ import androidx.test.core.app.ActivityScenario
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.fnives.test.showcase.R
import org.fnives.test.showcase.network.mockserver.scenario.auth.AuthScenario
import org.fnives.test.showcase.testutils.MockServerScenarioSetupTestRule
import org.fnives.test.showcase.testutils.configuration.SpecificTestConfigurationsFactory
import org.fnives.test.showcase.testutils.idling.Disposable
import org.fnives.test.showcase.testutils.idling.NetworkSynchronization
import org.fnives.test.showcase.testutils.MockServerScenarioSetupResetingTestRule
import org.fnives.test.showcase.testutils.configuration.MainDispatcherTestRule
import org.fnives.test.showcase.testutils.robot.RobotTestRule
import org.fnives.test.showcase.ui.auth.AuthActivity
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import org.junit.runner.RunWith
import org.koin.test.KoinTest
@ -23,31 +21,20 @@ class AuthActivityTest : KoinTest {
private lateinit var activityScenario: ActivityScenario<AuthActivity>
@Rule
@JvmField
val robotRule = RobotTestRule(LoginRobot())
private val loginRobot get() = robotRule.robot
private val mockServerScenarioSetupTestRule = MockServerScenarioSetupResetingTestRule()
private val mockServerScenarioSetup get() = mockServerScenarioSetupTestRule.mockServerScenarioSetup
private val mainDispatcherTestRule = MainDispatcherTestRule()
private val robot = LoginRobot()
@Rule
@JvmField
val mockServerScenarioSetupTestRule = MockServerScenarioSetupTestRule()
val mockServerScenarioSetup get() = mockServerScenarioSetupTestRule.mockServerScenarioSetup
@Rule
@JvmField
val mainDispatcherTestRule = SpecificTestConfigurationsFactory.createMainDispatcherTestRule()
private lateinit var disposable: Disposable
@Before
fun setUp() {
disposable = NetworkSynchronization.registerNetworkingSynchronization()
}
val ruleOrder: RuleChain = RuleChain.outerRule(mockServerScenarioSetupTestRule)
.around(mainDispatcherTestRule)
.around(RobotTestRule(robot))
@After
fun tearDown() {
activityScenario.close()
disposable.dispose()
}
/** GIVEN non empty password and username and successful response WHEN signIn THEN no error is shown and navigating to home */
@ -57,7 +44,7 @@ class AuthActivityTest : KoinTest {
AuthScenario.Success(password = "alma", username = "banan")
)
activityScenario = ActivityScenario.launch(AuthActivity::class.java)
loginRobot
robot
.setPassword("alma")
.setUsername("banan")
.assertPassword("alma")
@ -66,21 +53,21 @@ class AuthActivityTest : KoinTest {
.assertLoadingBeforeRequests()
mainDispatcherTestRule.advanceUntilIdleOrActivityIsDestroyed()
loginRobot.assertNavigatedToHome()
robot.assertNavigatedToHome()
}
/** GIVEN empty password and username WHEN signIn THEN error password is shown */
@Test
fun emptyPasswordShowsProperErrorMessage() {
activityScenario = ActivityScenario.launch(AuthActivity::class.java)
loginRobot
robot
.setUsername("banan")
.assertUsername("banan")
.clickOnLogin()
.assertLoadingBeforeRequests()
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
loginRobot.assertErrorIsShown(R.string.password_is_invalid)
robot.assertErrorIsShown(R.string.password_is_invalid)
.assertNotNavigatedToHome()
.assertNotLoading()
}
@ -89,14 +76,14 @@ class AuthActivityTest : KoinTest {
@Test
fun emptyUserNameShowsProperErrorMessage() {
activityScenario = ActivityScenario.launch(AuthActivity::class.java)
loginRobot
robot
.setPassword("banan")
.assertPassword("banan")
.clickOnLogin()
.assertLoadingBeforeRequests()
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
loginRobot.assertErrorIsShown(R.string.username_is_invalid)
robot.assertErrorIsShown(R.string.username_is_invalid)
.assertNotNavigatedToHome()
.assertNotLoading()
}
@ -108,7 +95,7 @@ class AuthActivityTest : KoinTest {
AuthScenario.InvalidCredentials(username = "alma", password = "banan")
)
activityScenario = ActivityScenario.launch(AuthActivity::class.java)
loginRobot
robot
.setUsername("alma")
.setPassword("banan")
.assertUsername("alma")
@ -117,7 +104,7 @@ class AuthActivityTest : KoinTest {
.assertLoadingBeforeRequests()
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
loginRobot.assertErrorIsShown(R.string.credentials_invalid)
robot.assertErrorIsShown(R.string.credentials_invalid)
.assertNotNavigatedToHome()
.assertNotLoading()
}
@ -129,7 +116,7 @@ class AuthActivityTest : KoinTest {
AuthScenario.GenericError(username = "alma", password = "banan")
)
activityScenario = ActivityScenario.launch(AuthActivity::class.java)
loginRobot
robot
.setUsername("alma")
.setPassword("banan")
.assertUsername("alma")
@ -138,7 +125,7 @@ class AuthActivityTest : KoinTest {
.assertLoadingBeforeRequests()
mainDispatcherTestRule.advanceUntilIdleWithIdlingResources()
loginRobot.assertErrorIsShown(R.string.something_went_wrong)
robot.assertErrorIsShown(R.string.something_went_wrong)
.assertNotNavigatedToHome()
.assertNotLoading()
}

View file

@ -3,15 +3,15 @@ package org.fnives.test.showcase.ui.splash
import androidx.lifecycle.Lifecycle
import androidx.test.core.app.ActivityScenario
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.fnives.test.showcase.testutils.MockServerScenarioSetupTestRule
import org.fnives.test.showcase.testutils.configuration.SpecificTestConfigurationsFactory
import org.fnives.test.showcase.testutils.idling.Disposable
import org.fnives.test.showcase.testutils.idling.NetworkSynchronization
import org.fnives.test.showcase.testutils.MockServerScenarioSetupResetingTestRule
import org.fnives.test.showcase.testutils.configuration.MainDispatcherTestRule
import org.fnives.test.showcase.testutils.robot.RobotTestRule
import org.fnives.test.showcase.testutils.statesetup.SetupAuthenticationState.setupLogin
import org.fnives.test.showcase.testutils.statesetup.SetupAuthenticationState.setupLogout
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import org.junit.runner.RunWith
import org.koin.test.KoinTest
@ -21,44 +21,33 @@ class SplashActivityTest : KoinTest {
private lateinit var activityScenario: ActivityScenario<SplashActivity>
private val splashRobot: SplashRobot get() = robotTestRule.robot
private val mainDispatcherTestRule = MainDispatcherTestRule()
private val mockServerScenarioSetupTestRule = MockServerScenarioSetupResetingTestRule()
private val robot = SplashRobot()
@Rule
@JvmField
val robotTestRule = RobotTestRule(SplashRobot())
@Rule
@JvmField
val mainDispatcherTestRule = SpecificTestConfigurationsFactory.createMainDispatcherTestRule()
@Rule
@JvmField
val mockServerScenarioSetupTestRule = MockServerScenarioSetupTestRule()
lateinit var disposable: Disposable
@Before
fun setUp() {
disposable = NetworkSynchronization.registerNetworkingSynchronization()
}
val ruleOrder: RuleChain = RuleChain.outerRule(mockServerScenarioSetupTestRule)
.around(mainDispatcherTestRule)
.around(RobotTestRule(robot))
@After
fun tearDown() {
activityScenario.close()
disposable.dispose()
}
/** GIVEN loggedInState WHEN opened after some time THEN MainActivity is started */
@Test
fun loggedInStateNavigatesToHome() {
splashRobot.setupLoggedInState(mainDispatcherTestRule, mockServerScenarioSetupTestRule.mockServerScenarioSetup)
setupLogin(mainDispatcherTestRule, mockServerScenarioSetupTestRule.mockServerScenarioSetup)
activityScenario = ActivityScenario.launch(SplashActivity::class.java)
activityScenario.moveToState(Lifecycle.State.RESUMED)
mainDispatcherTestRule.advanceTimeBy(501)
splashRobot.assertHomeIsStarted()
robot.assertHomeIsStarted()
.assertAuthIsNotStarted()
workaroundForActivityScenarioCLoseLockingUp()
@ -67,13 +56,13 @@ class SplashActivityTest : KoinTest {
/** GIVEN loggedOffState WHEN opened after some time THEN AuthActivity is started */
@Test
fun loggedOutStatesNavigatesToAuthentication() {
splashRobot.setupLoggedOutState(mainDispatcherTestRule)
setupLogout(mainDispatcherTestRule)
activityScenario = ActivityScenario.launch(SplashActivity::class.java)
activityScenario.moveToState(Lifecycle.State.RESUMED)
mainDispatcherTestRule.advanceTimeBy(501)
splashRobot.assertAuthIsStarted()
robot.assertAuthIsStarted()
.assertHomeIsNotStarted()
workaroundForActivityScenarioCLoseLockingUp()
@ -82,27 +71,27 @@ class SplashActivityTest : KoinTest {
/** GIVEN loggedOffState and not enough time WHEN opened THEN no activity is started */
@Test
fun loggedOutStatesNotEnoughTime() {
splashRobot.setupLoggedOutState(mainDispatcherTestRule)
setupLogout(mainDispatcherTestRule)
activityScenario = ActivityScenario.launch(SplashActivity::class.java)
activityScenario.moveToState(Lifecycle.State.RESUMED)
mainDispatcherTestRule.advanceTimeBy(10)
splashRobot.assertAuthIsNotStarted()
robot.assertAuthIsNotStarted()
.assertHomeIsNotStarted()
}
/** GIVEN loggedInState and not enough time WHEN opened THEN no activity is started */
@Test
fun loggedInStatesNotEnoughTime() {
splashRobot.setupLoggedInState(mainDispatcherTestRule, mockServerScenarioSetupTestRule.mockServerScenarioSetup)
setupLogin(mainDispatcherTestRule, mockServerScenarioSetupTestRule.mockServerScenarioSetup)
activityScenario = ActivityScenario.launch(SplashActivity::class.java)
activityScenario.moveToState(Lifecycle.State.RESUMED)
mainDispatcherTestRule.advanceTimeBy(10)
splashRobot.assertHomeIsNotStarted()
robot.assertHomeIsNotStarted()
.assertAuthIsNotStarted()
}

View file

@ -1,12 +1,8 @@
package org.fnives.test.showcase.ui.splash
import android.app.Instrumentation
import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.matcher.IntentMatchers
import org.fnives.test.showcase.network.mockserver.MockServerScenarioSetup
import org.fnives.test.showcase.testutils.configuration.MainDispatcherTestRule
import org.fnives.test.showcase.testutils.robot.Robot
import org.fnives.test.showcase.testutils.statesetup.SetupAuthenticationState
import org.fnives.test.showcase.testutils.viewactions.notIntended
import org.fnives.test.showcase.ui.auth.AuthActivity
import org.fnives.test.showcase.ui.home.MainActivity
@ -15,33 +11,12 @@ class SplashRobot : Robot {
override fun init() {
Intents.init()
Intents.intending(IntentMatchers.hasComponent(MainActivity::class.java.canonicalName))
.respondWith(Instrumentation.ActivityResult(0, null))
Intents.intending(IntentMatchers.hasComponent(AuthActivity::class.java.canonicalName))
.respondWith(Instrumentation.ActivityResult(0, null))
}
override fun release() {
Intents.release()
}
fun setupLoggedInState(
mainDispatcherTestRule: MainDispatcherTestRule,
mockServerScenarioSetup: MockServerScenarioSetup
) {
SetupAuthenticationState.setupLogin(mainDispatcherTestRule, mockServerScenarioSetup)
release()
init()
}
fun setupLoggedOutState(
mainDispatcherTestRule: MainDispatcherTestRule
) {
SetupAuthenticationState.setupLogout(mainDispatcherTestRule)
release()
init()
}
fun assertHomeIsStarted() = apply {
Intents.intended(IntentMatchers.hasComponent(MainActivity::class.java.canonicalName))
}