diff --git a/app/build.gradle b/app/build.gradle index 163f056..8bfc52f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -38,7 +38,7 @@ android { sourceSets { androidTest { - java.srcDirs += "src/sharedTest/java" +// java.srcDirs += "src/sharedTest/java" assets.srcDirs += files("$projectDir/schemas".toString()) } test { diff --git a/app/src/androidTest/java/org/fnives/test/showcase/testutils/configuration/AndroidTestServerTypeConfiguration.kt b/app/src/androidTest/java/org/fnives/test/showcase/testutils/configuration/AndroidTestServerTypeConfiguration.kt deleted file mode 100644 index 319668e..0000000 --- a/app/src/androidTest/java/org/fnives/test/showcase/testutils/configuration/AndroidTestServerTypeConfiguration.kt +++ /dev/null @@ -1,29 +0,0 @@ -package org.fnives.test.showcase.testutils.configuration - -import okhttp3.OkHttpClient -import org.fnives.test.showcase.network.mockserver.MockServerScenarioSetup -import org.fnives.test.showcase.testutils.idling.NetworkSynchronization -import org.koin.core.context.loadKoinModules -import org.koin.core.qualifier.StringQualifier -import org.koin.dsl.module -import org.koin.test.KoinTest -import org.koin.test.get - -object AndroidTestServerTypeConfiguration : ServerTypeConfiguration, KoinTest { - override val useHttps: Boolean get() = true - - override val url: String get() = "${MockServerScenarioSetup.HTTPS_BASE_URL}:${MockServerScenarioSetup.PORT}/" - - override fun invoke(mockServerScenarioSetup: MockServerScenarioSetup) { - val handshakeCertificates = mockServerScenarioSetup.clientCertificates ?: return - val sessionless = StringQualifier(NetworkSynchronization.OkHttpClientTypes.SESSIONLESS.qualifier) - val okHttpClientWithCertificate = get(sessionless).newBuilder() - .sslSocketFactory(handshakeCertificates.sslSocketFactory(), handshakeCertificates.trustManager) - .build() - loadKoinModules( - module { - single(qualifier = sessionless) { okHttpClientWithCertificate } - } - ) - } -} diff --git a/app/src/androidTest/java/org/fnives/test/showcase/testutils/configuration/SpecificTestConfigurationsFactory.kt b/app/src/androidTest/java/org/fnives/test/showcase/testutils/configuration/SpecificTestConfigurationsFactory.kt index 90680c0..6a3da36 100644 --- a/app/src/androidTest/java/org/fnives/test/showcase/testutils/configuration/SpecificTestConfigurationsFactory.kt +++ b/app/src/androidTest/java/org/fnives/test/showcase/testutils/configuration/SpecificTestConfigurationsFactory.kt @@ -4,9 +4,6 @@ object SpecificTestConfigurationsFactory : TestConfigurationsFactory { override fun createMainDispatcherTestRule(): MainDispatcherTestRule = AndroidTestMainDispatcherTestRule() - override fun createServerTypeConfiguration(): ServerTypeConfiguration = - AndroidTestServerTypeConfiguration - override fun createLoginRobotConfiguration(): LoginRobotConfiguration = AndroidTestLoginRobotConfiguration diff --git a/app/src/robolectricTest/java/org/fnives/test/showcase/testutils/configuration/RobolectricServerTypeConfiguration.kt b/app/src/robolectricTest/java/org/fnives/test/showcase/testutils/configuration/RobolectricServerTypeConfiguration.kt deleted file mode 100644 index 895f466..0000000 --- a/app/src/robolectricTest/java/org/fnives/test/showcase/testutils/configuration/RobolectricServerTypeConfiguration.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.fnives.test.showcase.testutils.configuration - -import org.fnives.test.showcase.network.mockserver.MockServerScenarioSetup - -object RobolectricServerTypeConfiguration : ServerTypeConfiguration { - override val useHttps: Boolean = false - - override val url: String get() = "${MockServerScenarioSetup.HTTP_BASE_URL}:${MockServerScenarioSetup.PORT}/" - - override fun invoke(mockServerScenarioSetup: MockServerScenarioSetup) = Unit -} diff --git a/app/src/robolectricTest/java/org/fnives/test/showcase/testutils/configuration/SpecificTestConfigurationsFactory.kt b/app/src/robolectricTest/java/org/fnives/test/showcase/testutils/configuration/SpecificTestConfigurationsFactory.kt index 5028a4b..ff7e7af 100644 --- a/app/src/robolectricTest/java/org/fnives/test/showcase/testutils/configuration/SpecificTestConfigurationsFactory.kt +++ b/app/src/robolectricTest/java/org/fnives/test/showcase/testutils/configuration/SpecificTestConfigurationsFactory.kt @@ -4,9 +4,6 @@ object SpecificTestConfigurationsFactory : TestConfigurationsFactory { override fun createMainDispatcherTestRule(): MainDispatcherTestRule = TestCoroutineMainDispatcherTestRule() - override fun createServerTypeConfiguration(): ServerTypeConfiguration = - RobolectricServerTypeConfiguration - override fun createLoginRobotConfiguration(): LoginRobotConfiguration = RobolectricLoginRobotConfiguration diff --git a/app/src/sharedTest/java/org/fnives/test/showcase/testutils/MockServerScenarioSetupTestRule.kt b/app/src/sharedTest/java/org/fnives/test/showcase/testutils/MockServerScenarioSetupTestRule.kt index df076ab..36755f0 100644 --- a/app/src/sharedTest/java/org/fnives/test/showcase/testutils/MockServerScenarioSetupTestRule.kt +++ b/app/src/sharedTest/java/org/fnives/test/showcase/testutils/MockServerScenarioSetupTestRule.kt @@ -1,35 +1,63 @@ package org.fnives.test.showcase.testutils +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.configuration.ServerTypeConfiguration -import org.fnives.test.showcase.testutils.configuration.SpecificTestConfigurationsFactory -import org.junit.rules.TestRule +import org.fnives.test.showcase.testutils.idling.NetworkSynchronization.OkHttpClientTypes import org.junit.runner.Description import org.junit.runners.model.Statement +import org.koin.core.context.loadKoinModules +import org.koin.dsl.module +import org.koin.test.KoinTest +import org.koin.test.get + +class MockServerScenarioSetupTestRule : ReloadKoinModulesIfNecessaryTestRule(), KoinTest { -class MockServerScenarioSetupTestRule( - val serverTypeConfiguration: ServerTypeConfiguration = SpecificTestConfigurationsFactory.createServerTypeConfiguration() -) : TestRule { lateinit var mockServerScenarioSetup: MockServerScenarioSetup + private val sessionlessQualifier get() = OkHttpClientTypes.SESSIONLESS.asQualifier() + override fun apply(base: Statement, description: Description): Statement = - object : Statement() { - @Throws(Throwable::class) - override fun evaluate() { - before() - try { - base.evaluate() - } finally { - after() - } + super.apply(createStatement(base), description) + + private fun createStatement(base: Statement) = object : Statement() { + @Throws(Throwable::class) + override fun evaluate() { + before() + try { + base.evaluate() + } finally { + after() } } + } private fun before() { mockServerScenarioSetup = MockServerScenarioSetup() - mockServerScenarioSetup.start(serverTypeConfiguration.useHttps) + val url = mockServerScenarioSetup.start(true) + + val handshakeCertificates = mockServerScenarioSetup.clientCertificates + ?: throw IllegalStateException("ClientCertificate should be accessable") + + val okHttpClientWithCertificate = createUpdateOkHttpClient(handshakeCertificates) + + loadKoinModules( + module { + // add https certificate to okhttp + single(qualifier = sessionlessQualifier) { okHttpClientWithCertificate } + // replace base url with mockWebServer's + single { BaseUrl(url) } + } + ) } + private fun createUpdateOkHttpClient(handshakeCertificates: HandshakeCertificates) = + get(sessionlessQualifier).newBuilder() + .sslSocketFactory(handshakeCertificates.sslSocketFactory(), handshakeCertificates.trustManager) + .build() + + private fun after() { mockServerScenarioSetup.stop() } diff --git a/app/src/sharedTest/java/org/fnives/test/showcase/testutils/ReloadKoinModulesIfNecessaryTestRule.kt b/app/src/sharedTest/java/org/fnives/test/showcase/testutils/ReloadKoinModulesIfNecessaryTestRule.kt index b3d7c6b..e241826 100644 --- a/app/src/sharedTest/java/org/fnives/test/showcase/testutils/ReloadKoinModulesIfNecessaryTestRule.kt +++ b/app/src/sharedTest/java/org/fnives/test/showcase/testutils/ReloadKoinModulesIfNecessaryTestRule.kt @@ -1,28 +1,50 @@ package org.fnives.test.showcase.testutils +import androidx.test.core.app.ApplicationProvider +import org.fnives.test.showcase.BuildConfig +import org.fnives.test.showcase.TestShowcaseApplication +import org.fnives.test.showcase.di.createAppModules +import org.fnives.test.showcase.model.network.BaseUrl 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.startKoin import org.koin.core.context.stopKoin +import org.koin.mp.KoinPlatformTools +import org.koin.test.KoinTest -class ReloadKoinModulesIfNecessaryTestRule : TestRule { +/** + * Test rule to help reinitialize the whole Koin setup. + * + * It's needed because in AndroidTest's the Application is only called once, + * meaning our koin would be shared. + * + * 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 { override fun apply(base: Statement, description: Description): Statement = - object : Statement() { - override fun evaluate() { - // TODO -// if (GlobalContext.getOrNull() == null) { -// val application = -// ApplicationProvider.getApplicationContext() -// startKoin { -// androidContext(application) -// modules(createAppModules(BaseUrlProvider.get())) -// } -// } - try { - base.evaluate() - } finally { - stopKoin() - } + ReinitKoinStatement(base) + + class ReinitKoinStatement(private val base: Statement) : Statement() { + override fun evaluate() { + reinitKoinIfNeeded() + try { + base.evaluate() + } finally { + stopKoin() } } + + private fun reinitKoinIfNeeded() { + if (KoinPlatformTools.defaultContext().getOrNull() != null) return + + val application = ApplicationProvider.getApplicationContext() + val baseUrl = BaseUrl(BuildConfig.BASE_URL) + startKoin { + androidContext(application) + modules(createAppModules(baseUrl)) + } + } + } } diff --git a/app/src/sharedTest/java/org/fnives/test/showcase/testutils/configuration/TestConfigurationsFactory.kt b/app/src/sharedTest/java/org/fnives/test/showcase/testutils/configuration/TestConfigurationsFactory.kt index ed406a1..3ac0428 100644 --- a/app/src/sharedTest/java/org/fnives/test/showcase/testutils/configuration/TestConfigurationsFactory.kt +++ b/app/src/sharedTest/java/org/fnives/test/showcase/testutils/configuration/TestConfigurationsFactory.kt @@ -10,8 +10,6 @@ interface TestConfigurationsFactory { fun createMainDispatcherTestRule(): MainDispatcherTestRule - fun createServerTypeConfiguration(): ServerTypeConfiguration - fun createLoginRobotConfiguration(): LoginRobotConfiguration fun createSnackbarVerification(): SnackbarVerificationTestRule diff --git a/app/src/sharedTest/java/org/fnives/test/showcase/testutils/idling/NetworkSynchronization.kt b/app/src/sharedTest/java/org/fnives/test/showcase/testutils/idling/NetworkSynchronization.kt index 7bcb095..135dce1 100644 --- a/app/src/sharedTest/java/org/fnives/test/showcase/testutils/idling/NetworkSynchronization.kt +++ b/app/src/sharedTest/java/org/fnives/test/showcase/testutils/idling/NetworkSynchronization.kt @@ -21,12 +21,14 @@ object NetworkSynchronization : KoinTest { return CompositeDisposable(idlingResources) } - private fun getOkHttpClient(type: OkHttpClientTypes): OkHttpClient = get(StringQualifier(type.qualifier)) + private fun getOkHttpClient(type: OkHttpClientTypes): OkHttpClient = get(type.asQualifier()) private fun OkHttpClient.asIdlingResource(name: String): IdlingResource = OkHttp3IdlingResource.create(name, this) enum class OkHttpClientTypes(val qualifier: String) { - SESSION("SESSION-NETWORKING"), SESSIONLESS("SESSIONLESS-NETWORKING") + SESSION("SESSION-NETWORKING"), SESSIONLESS("SESSIONLESS-NETWORKING"); + + fun asQualifier() = StringQualifier(qualifier) } } diff --git a/app/src/sharedTest/java/org/fnives/test/showcase/ui/home/MainActivityTest.kt b/app/src/sharedTest/java/org/fnives/test/showcase/ui/home/MainActivityTest.kt index e4ff3a2..0607d99 100644 --- a/app/src/sharedTest/java/org/fnives/test/showcase/ui/home/MainActivityTest.kt +++ b/app/src/sharedTest/java/org/fnives/test/showcase/ui/home/MainActivityTest.kt @@ -8,7 +8,6 @@ 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.ReloadKoinModulesIfNecessaryTestRule import org.fnives.test.showcase.testutils.configuration.SpecificTestConfigurationsFactory import org.fnives.test.showcase.testutils.idling.Disposable import org.fnives.test.showcase.testutils.idling.NetworkSynchronization @@ -52,16 +51,10 @@ class MainActivityTest : KoinTest { @JvmField val mainDispatcherTestRule = SpecificTestConfigurationsFactory.createMainDispatcherTestRule() - @Rule - @JvmField - val reloadKoinModulesIfNecessaryTestRule = ReloadKoinModulesIfNecessaryTestRule() - private lateinit var disposable: Disposable @Before fun setUp() { - SpecificTestConfigurationsFactory.createServerTypeConfiguration() - .invoke(mockServerScenarioSetup) disposable = NetworkSynchronization.registerNetworkingSynchronization() homeRobot.setupLogin( diff --git a/app/src/sharedTest/java/org/fnives/test/showcase/ui/login/AuthActivityTest.kt b/app/src/sharedTest/java/org/fnives/test/showcase/ui/login/AuthActivityTest.kt index f725e74..e81b091 100644 --- a/app/src/sharedTest/java/org/fnives/test/showcase/ui/login/AuthActivityTest.kt +++ b/app/src/sharedTest/java/org/fnives/test/showcase/ui/login/AuthActivityTest.kt @@ -6,7 +6,6 @@ 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.ReloadKoinModulesIfNecessaryTestRule import org.fnives.test.showcase.testutils.configuration.SpecificTestConfigurationsFactory import org.fnives.test.showcase.testutils.idling.Disposable import org.fnives.test.showcase.testutils.idling.NetworkSynchronization @@ -47,16 +46,10 @@ class AuthActivityTest : KoinTest { @JvmField val mainDispatcherTestRule = SpecificTestConfigurationsFactory.createMainDispatcherTestRule() - @Rule - @JvmField - val reloadKoinModulesIfNecessaryTestRule = ReloadKoinModulesIfNecessaryTestRule() - private lateinit var disposable: Disposable @Before fun setUp() { - SpecificTestConfigurationsFactory.createServerTypeConfiguration() - .invoke(mockServerScenarioSetup) disposable = NetworkSynchronization.registerNetworkingSynchronization() } diff --git a/app/src/sharedTest/java/org/fnives/test/showcase/ui/splash/SplashActivityTest.kt b/app/src/sharedTest/java/org/fnives/test/showcase/ui/splash/SplashActivityTest.kt index ac904e2..71fabde 100644 --- a/app/src/sharedTest/java/org/fnives/test/showcase/ui/splash/SplashActivityTest.kt +++ b/app/src/sharedTest/java/org/fnives/test/showcase/ui/splash/SplashActivityTest.kt @@ -4,7 +4,6 @@ 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.ReloadKoinModulesIfNecessaryTestRule import org.fnives.test.showcase.testutils.configuration.SpecificTestConfigurationsFactory import org.fnives.test.showcase.testutils.idling.Disposable import org.fnives.test.showcase.testutils.idling.NetworkSynchronization @@ -36,16 +35,10 @@ class SplashActivityTest : KoinTest { @JvmField val mockServerScenarioSetupTestRule = MockServerScenarioSetupTestRule() - @Rule - @JvmField - val reloadKoinModulesIfNecessaryTestRule = ReloadKoinModulesIfNecessaryTestRule() - lateinit var disposable: Disposable @Before fun setUp() { - SpecificTestConfigurationsFactory.createServerTypeConfiguration() - .invoke(mockServerScenarioSetupTestRule.mockServerScenarioSetup) disposable = NetworkSynchronization.registerNetworkingSynchronization() } diff --git a/network/src/main/java/org/fnives/test/showcase/network/di/createNetworkmodules.kt b/network/src/main/java/org/fnives/test/showcase/network/di/createNetworkmodules.kt index b4b0e8b..019faa7 100644 --- a/network/src/main/java/org/fnives/test/showcase/network/di/createNetworkmodules.kt +++ b/network/src/main/java/org/fnives/test/showcase/network/di/createNetworkmodules.kt @@ -29,12 +29,17 @@ fun createNetworkModules( networkSessionExpirationListenerProvider: Scope.() -> NetworkSessionExpirationListener ): Sequence = sequenceOf( + baseUrlModule(baseUrl), loginModule(), contentModule(), - sessionlessNetworkingModule(baseUrl, enableLogging), + sessionlessNetworkingModule(enableLogging), sessionNetworkingModule(networkSessionLocalStorageProvider, networkSessionExpirationListenerProvider) ) +private fun baseUrlModule(baseUrl: BaseUrl) = module { + single { baseUrl } +} + private fun loginModule() = module { factory { LoginRemoteSourceImpl(get(), get()) } factory { get() } @@ -48,7 +53,7 @@ private fun contentModule() = module { factory { get() } } -private fun sessionlessNetworkingModule(baseUrl: BaseUrl, enableLogging: Boolean) = module { +private fun sessionlessNetworkingModule(enableLogging: Boolean) = module { factory { MoshiConverterFactory.create() } single(qualifier = sessionless) { OkHttpClient.Builder() @@ -58,7 +63,7 @@ private fun sessionlessNetworkingModule(baseUrl: BaseUrl, enableLogging: Boolean } single(qualifier = sessionless) { Retrofit.Builder() - .baseUrl(baseUrl.baseUrl) + .baseUrl(get().baseUrl) .addConverterFactory(get()) .client(get(sessionless)) .build()