Fix swapping out Database in tests

Previously overwrote the object itself for a quick swap of DatabaseInitialization, but that only works over API 24.
So now we will use loadKoinModules instead, which resolves the issue on ani API level
This commit is contained in:
Gergely Hegedus 2022-04-13 19:13:34 +03:00
parent 78a877b0c9
commit 1d2ca90203
11 changed files with 57 additions and 47 deletions

View file

@ -12,12 +12,12 @@ import androidx.test.runner.AndroidJUnit4
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import org.fnives.test.showcase.R
import org.fnives.test.showcase.network.testutil.NetworkTestConfigurationHelper
import org.fnives.test.showcase.storage.database.DatabaseInitialization
import org.fnives.test.showcase.testutils.idling.CompositeDisposable
import org.fnives.test.showcase.testutils.idling.Disposable
import org.fnives.test.showcase.testutils.idling.IdlingResourceDisposable
import org.fnives.test.showcase.testutils.idling.OkHttp3IdlingResource
import org.fnives.test.showcase.testutils.idling.loopMainThreadFor
import org.fnives.test.showcase.testutils.storage.TestDatabaseInitialization
import org.fnives.test.showcase.ui.splash.SplashActivity
import org.hamcrest.Description
import org.hamcrest.Matcher
@ -45,7 +45,7 @@ class LoginLogoutEndToEndTest {
@Before
fun before() {
/** Needed to add the dispatcher to the Database */
DatabaseInitialization.dispatcher = UnconfinedTestDispatcher()
TestDatabaseInitialization.overwriteDatabaseInitialization(UnconfinedTestDispatcher())
/** Needed to register the Okhttp as Idling resource, so Espresso actually waits for the response.*/
val idlingResources = NetworkTestConfigurationHelper.getOkHttpClients()

View file

@ -12,7 +12,7 @@ import kotlinx.coroutines.test.runTest
import org.fnives.test.showcase.core.integration.fake.FakeFavouriteContentLocalStorage
import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage
import org.fnives.test.showcase.model.content.ContentId
import org.fnives.test.showcase.storage.database.DatabaseInitialization
import org.fnives.test.showcase.testutils.storage.TestDatabaseInitialization
import org.junit.After
import org.junit.Assert
import org.junit.Before
@ -36,7 +36,7 @@ internal class FavouriteContentLocalStorageImplInstrumentedTest(
@Before
fun setUp() {
testDispatcher = StandardTestDispatcher()
DatabaseInitialization.dispatcher = testDispatcher
TestDatabaseInitialization.overwriteDatabaseInitialization(testDispatcher)
sut = favouriteContentLocalStorageFactory()
}

View file

@ -14,13 +14,13 @@ import org.fnives.test.showcase.R
import org.fnives.test.showcase.network.mockserver.MockServerScenarioSetup
import org.fnives.test.showcase.network.mockserver.scenario.auth.AuthScenario
import org.fnives.test.showcase.network.testutil.NetworkTestConfigurationHelper
import org.fnives.test.showcase.storage.database.DatabaseInitialization
import org.fnives.test.showcase.testutils.idling.CompositeDisposable
import org.fnives.test.showcase.testutils.idling.Disposable
import org.fnives.test.showcase.testutils.idling.IdlingResourceDisposable
import org.fnives.test.showcase.testutils.idling.MainDispatcherTestRule.Companion.advanceUntilIdleWithIdlingResources
import org.fnives.test.showcase.testutils.idling.OkHttp3IdlingResource
import org.fnives.test.showcase.testutils.safeClose
import org.fnives.test.showcase.testutils.storage.TestDatabaseInitialization
import org.fnives.test.showcase.ui.auth.AuthActivity
import org.junit.After
import org.junit.Before
@ -45,7 +45,7 @@ class RobolectricAuthActivityInstrumentedTest : KoinTest {
val dispatcher = StandardTestDispatcher()
Dispatchers.setMain(dispatcher)
testDispatcher = dispatcher
DatabaseInitialization.dispatcher = dispatcher
TestDatabaseInitialization.overwriteDatabaseInitialization(dispatcher)
mockServerScenarioSetup = NetworkTestConfigurationHelper.startWithHTTPSMockWebServer()

View file

@ -1,21 +0,0 @@
package org.fnives.test.showcase.storage.database
import android.content.Context
import androidx.room.Room
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.asExecutor
import org.fnives.test.showcase.storage.LocalDatabase
object DatabaseInitialization {
lateinit var dispatcher: CoroutineDispatcher
fun create(context: Context): LocalDatabase {
val executor = dispatcher.asExecutor()
return Room.inMemoryDatabaseBuilder(context, LocalDatabase::class.java)
.setTransactionExecutor(executor)
.setQueryExecutor(executor)
.allowMainThreadQueries()
.build()
}
}

View file

@ -3,8 +3,8 @@ package org.fnives.test.showcase.testutils.idling
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestDispatcher
import org.fnives.test.showcase.storage.database.DatabaseInitialization
import org.fnives.test.showcase.testutils.runOnUIAwaitOnCurrent
import org.fnives.test.showcase.testutils.storage.TestDatabaseInitialization
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
@ -20,7 +20,7 @@ class DispatcherTestRule : TestRule {
override fun evaluate() {
val dispatcher = StandardTestDispatcher()
testDispatcher = dispatcher
DatabaseInitialization.dispatcher = dispatcher
TestDatabaseInitialization.overwriteDatabaseInitialization(dispatcher)
base.evaluate()
}
}

View file

@ -6,8 +6,8 @@ import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain
import org.fnives.test.showcase.storage.database.DatabaseInitialization
import org.fnives.test.showcase.testutils.runOnUIAwaitOnCurrent
import org.fnives.test.showcase.testutils.storage.TestDatabaseInitialization
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
@ -24,7 +24,7 @@ class MainDispatcherTestRule : TestRule {
val dispatcher = StandardTestDispatcher()
Dispatchers.setMain(dispatcher)
testDispatcher = dispatcher
DatabaseInitialization.dispatcher = dispatcher
TestDatabaseInitialization.overwriteDatabaseInitialization(dispatcher)
try {
base.evaluate()
} finally {

View file

@ -0,0 +1,31 @@
package org.fnives.test.showcase.testutils.storage
import android.content.Context
import androidx.room.Room
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.asExecutor
import org.fnives.test.showcase.storage.LocalDatabase
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.loadKoinModules
import org.koin.dsl.module
/**
* Reloads the Database Koin module, so it uses the inMemory database with the switched out Executors.
*/
object TestDatabaseInitialization {
fun create(context: Context, dispatcher: CoroutineDispatcher): LocalDatabase {
val executor = dispatcher.asExecutor()
return Room.inMemoryDatabaseBuilder(context, LocalDatabase::class.java)
.setTransactionExecutor(executor)
.setQueryExecutor(executor)
.allowMainThreadQueries()
.build()
}
fun overwriteDatabaseInitialization(dispatcher: CoroutineDispatcher) {
loadKoinModules(module {
single { create(androidContext(), dispatcher) }
})
}
}

View file

@ -8,6 +8,7 @@ import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain
import org.fnives.test.showcase.storage.database.DatabaseInitialization
import org.fnives.test.showcase.testutils.storage.TestDatabaseInitialization
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
@ -28,7 +29,7 @@ class PlainMainDispatcherRule(private val useStandard: Boolean = true) : TestRul
try {
val dispatcher = if (useStandard) StandardTestDispatcher() else UnconfinedTestDispatcher()
Dispatchers.setMain(dispatcher)
DatabaseInitialization.dispatcher = dispatcher
TestDatabaseInitialization.overwriteDatabaseInitialization(dispatcher)
_testDispatcher = dispatcher
base.evaluate()
} finally {

View file

@ -6,14 +6,13 @@ import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain
import org.fnives.test.showcase.storage.database.DatabaseInitialization
import org.fnives.test.showcase.testutils.TestMainDispatcher.Companion.testDispatcher
import org.junit.jupiter.api.extension.AfterEachCallback
import org.junit.jupiter.api.extension.BeforeEachCallback
import org.junit.jupiter.api.extension.ExtensionContext
/**
* Custom Junit5 Extension which replaces the [DatabaseInitialization]'s dispatcher and main dispatcher with a [TestDispatcher]
* Custom Junit5 Extension which replaces the main dispatcher with a [TestDispatcher]
*
* One can access the test dispatcher via [testDispatcher] static getter.
*/
@ -23,7 +22,6 @@ class TestMainDispatcher : BeforeEachCallback, AfterEachCallback {
override fun beforeEach(context: ExtensionContext?) {
val testDispatcher = StandardTestDispatcher()
privateTestDispatcher = testDispatcher
DatabaseInitialization.dispatcher = testDispatcher
Dispatchers.setMain(testDispatcher)
}