mirror of
https://github.com/uber/RIBs.git
synced 2026-06-16 12:54:31 +00:00
Fix test rule and add exception handler test
This commit is contained in:
@@ -22,11 +22,7 @@ import com.facebook.flipper.core.FlipperClient
|
||||
import com.facebook.flipper.plugins.inspector.DescriptorMapping
|
||||
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin
|
||||
import com.facebook.soloader.SoLoader
|
||||
import com.uber.rib.core.RibDispatchersConfig
|
||||
import com.uber.rib.core.RibDispatchersProvider
|
||||
import com.uber.rib.flipper.RibTreePlugin
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.MainCoroutineDispatcher
|
||||
|
||||
class ComposeApplication : Application() {
|
||||
|
||||
|
||||
+22
-21
@@ -1,32 +1,33 @@
|
||||
package com.uber.rib.core
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.TestCoroutineDispatcher
|
||||
import kotlinx.coroutines.test.resetMain
|
||||
import kotlinx.coroutines.test.setMain
|
||||
import org.junit.rules.TestRule
|
||||
import org.junit.rules.TestWatcher
|
||||
import org.junit.runner.Description
|
||||
import org.junit.runners.model.Statement
|
||||
|
||||
class RibDispatchersRule : TestRule {
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override fun apply(base: Statement, description: Description) = object : Statement() {
|
||||
override fun evaluate() {
|
||||
Dispatchers.setMain(TestCoroutineDispatcher())
|
||||
RibDispatchersConfig.delegate = DefaultRibDispatcherProvider(
|
||||
Default = TestCoroutineDispatcher(),
|
||||
Main = Dispatchers.Main,
|
||||
IO = TestCoroutineDispatcher(),
|
||||
Unconfined = TestCoroutineDispatcher())
|
||||
class RibDispatchersRule : TestWatcher() {
|
||||
|
||||
Dispatchers.Main
|
||||
try {
|
||||
base.evaluate()
|
||||
} finally {
|
||||
Dispatchers.resetMain()
|
||||
RibDispatchersConfig.reset()
|
||||
}
|
||||
}
|
||||
override fun starting(description: Description) {
|
||||
val defaultDispatcher = TestCoroutineDispatcher()
|
||||
val mainDispatcher = TestCoroutineDispatcher()
|
||||
val ioDispatcher = TestCoroutineDispatcher()
|
||||
val unconfinedDispatcher = TestCoroutineDispatcher()
|
||||
|
||||
Dispatchers.setMain(mainDispatcher)
|
||||
|
||||
val mainDispatcherProxy = Dispatchers.Main
|
||||
|
||||
RibCoroutinesConfig.dispatchers = DefaultRibDispatcherProvider(
|
||||
Default = defaultDispatcher,
|
||||
Main = mainDispatcherProxy,
|
||||
IO = ioDispatcher,
|
||||
Unconfined = unconfinedDispatcher)
|
||||
}
|
||||
|
||||
override fun finished(description: Description) {
|
||||
Dispatchers.resetMain()
|
||||
RibCoroutinesConfig.reset()
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.uber.rib.core
|
||||
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
|
||||
object RibCoroutinesConfig {
|
||||
/**
|
||||
* Specify [RibDispatchersProvider] that provide default [CoroutineDispatcher]'s for Rib based scopes.
|
||||
* Defaults to standard [Dispatchers].
|
||||
* Useful in areas where injecting Dispatchers is not ideal, such as Test.
|
||||
*/
|
||||
@JvmStatic
|
||||
var dispatchers = createDefaultDispatchers()
|
||||
|
||||
/**
|
||||
* Specify [CoroutineExceptionHandler] to be used with Rib based scopes.
|
||||
* Defaults to throwing exception.
|
||||
* Useful for specifying additional information before passed to [Thread.UncaughtExceptionHandler].
|
||||
*/
|
||||
@JvmStatic
|
||||
var exceptionHandler = createDefaultExceptionHandler()
|
||||
|
||||
/**
|
||||
* Resets delegate to default [RibDispatchersProvider].
|
||||
* Should be called after tests
|
||||
*/
|
||||
@JvmStatic
|
||||
fun reset() {
|
||||
this.dispatchers = createDefaultDispatchers()
|
||||
this.exceptionHandler = createDefaultExceptionHandler()
|
||||
}
|
||||
|
||||
private fun createDefaultDispatchers() = DefaultRibDispatcherProvider()
|
||||
|
||||
private fun createDefaultExceptionHandler() = CoroutineExceptionHandler { _, throwable ->
|
||||
throw (throwable)
|
||||
}
|
||||
|
||||
}
|
||||
+4
-24
@@ -5,30 +5,10 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.MainCoroutineDispatcher
|
||||
|
||||
object RibDispatchers : RibDispatchersProvider {
|
||||
override val Default get() = RibDispatchersConfig.delegate.Default
|
||||
override val Main get() = RibDispatchersConfig.delegate.Main
|
||||
override val IO get() = RibDispatchersConfig.delegate.IO
|
||||
override val Unconfined get() = RibDispatchersConfig.delegate.Unconfined
|
||||
}
|
||||
|
||||
object RibDispatchersConfig {
|
||||
/**
|
||||
* Delegate used to override default Dispatchers.
|
||||
* Useful in areas where injecting Dispatchers is not ideal, such as Test.
|
||||
*/
|
||||
@JvmStatic
|
||||
var delegate = createDefaultRibDispatchers()
|
||||
|
||||
/**
|
||||
* Resets delegate to default [RibDispatchersProvider].
|
||||
* Should be called after tests
|
||||
*/
|
||||
@JvmStatic
|
||||
fun reset() {
|
||||
this.delegate = createDefaultRibDispatchers()
|
||||
}
|
||||
|
||||
private fun createDefaultRibDispatchers() = DefaultRibDispatcherProvider()
|
||||
override val Default get() = RibCoroutinesConfig.dispatchers.Default
|
||||
override val Main get() = RibCoroutinesConfig.dispatchers.Main
|
||||
override val IO get() = RibCoroutinesConfig.dispatchers.IO
|
||||
override val Unconfined get() = RibCoroutinesConfig.dispatchers.Unconfined
|
||||
}
|
||||
|
||||
class DefaultRibDispatcherProvider(override val Default : CoroutineDispatcher = Dispatchers.Default,
|
||||
|
||||
@@ -9,23 +9,23 @@ import java.util.*
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
val ScopeProvider.defaultScope by LazyWithReceiver<ScopeProvider, CoroutineScope> {
|
||||
asCoroutineScope(SupervisorJob() + scopeName(this, "defaultScope") + RibDispatchers.Default)
|
||||
asCoroutineScope( defaults(this, "defaultScope") + RibDispatchers.Default)
|
||||
}
|
||||
|
||||
val ScopeProvider.mainScope by LazyWithReceiver<ScopeProvider, CoroutineScope> {
|
||||
asCoroutineScope(SupervisorJob() + scopeName(this, "mainScope") + RibDispatchers.Main.immediate)
|
||||
asCoroutineScope(defaults(this, "mainScope") + RibDispatchers.Main.immediate)
|
||||
}
|
||||
|
||||
val ScopeProvider.ioScope by LazyWithReceiver<ScopeProvider, CoroutineScope> {
|
||||
asCoroutineScope(SupervisorJob() + scopeName(this, "ioScope") + RibDispatchers.IO)
|
||||
asCoroutineScope(defaults(this, "ioScope") + RibDispatchers.IO)
|
||||
}
|
||||
val ScopeProvider.unconfinedScope by LazyWithReceiver<ScopeProvider, CoroutineScope> {
|
||||
asCoroutineScope(SupervisorJob() + scopeName(this, "unconfinedScope") + RibDispatchers.Unconfined)
|
||||
asCoroutineScope(defaults(this, "unconfinedScope") + RibDispatchers.Unconfined)
|
||||
}
|
||||
|
||||
private fun scopeName(scopeProvider : ScopeProvider, scopeName: String) = CoroutineName("${scopeProvider::class.simpleName}:${scopeName}")
|
||||
private fun defaults(scopeProvider : ScopeProvider, scopeName: String) = SupervisorJob() + RibCoroutinesConfig.exceptionHandler + CoroutineName("${scopeProvider::class.simpleName}:${scopeName}")
|
||||
|
||||
private class LazyWithReceiver<This,Return>(val initializer:This.()->Return)
|
||||
internal class LazyWithReceiver<This,Return>(val initializer:This.()->Return)
|
||||
{
|
||||
private val values = WeakHashMap<This,Return>()
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ class RibDispatchersTest {
|
||||
assertThat(RibDispatchers.Main).isNotEqualTo(testDispatcher.Main)
|
||||
assertThat(RibDispatchers.Unconfined).isNotEqualTo(testDispatcher.Unconfined)
|
||||
|
||||
RibDispatchersConfig.delegate = testDispatcher
|
||||
RibCoroutinesConfig.dispatchers = testDispatcher
|
||||
|
||||
assertThat(RibDispatchers.Default).isEqualTo(testDispatcher.Default)
|
||||
assertThat(RibDispatchers.IO).isEqualTo(testDispatcher.IO)
|
||||
|
||||
+18
-20
@@ -2,34 +2,20 @@ package com.uber.rib.core
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.test.TestCoroutineDispatcher
|
||||
import kotlinx.coroutines.test.resetMain
|
||||
import kotlinx.coroutines.test.setMain
|
||||
import kotlinx.coroutines.test.*
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import java.lang.RuntimeException
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class RibScopesTest {
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
Dispatchers.setMain(TestCoroutineDispatcher())
|
||||
RibDispatchersConfig.delegate = DefaultRibDispatcherProvider(
|
||||
Default = TestCoroutineDispatcher(),
|
||||
Main = Dispatchers.Main,
|
||||
IO = TestCoroutineDispatcher(),
|
||||
Unconfined = TestCoroutineDispatcher())
|
||||
}
|
||||
|
||||
@After
|
||||
fun teardown() {
|
||||
Dispatchers.resetMain()
|
||||
RibDispatchersConfig.reset()
|
||||
}
|
||||
@get:Rule var rule = RibDispatchersRule()
|
||||
|
||||
@Test
|
||||
fun testScopeLifecycle() = runBlocking {
|
||||
fun testScopeLifecycle() = runBlockingTest {
|
||||
val interactor = FakeInteractor<Presenter, Router<*>>()
|
||||
interactor.attach()
|
||||
val job = interactor.mainScope.launch {
|
||||
@@ -42,7 +28,7 @@ class RibScopesTest {
|
||||
assertThat(job.isActive).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test()
|
||||
fun testScopeCaching() {
|
||||
|
||||
val interactor1 = FakeInteractor<Presenter, Router<*>>()
|
||||
@@ -58,5 +44,17 @@ class RibScopesTest {
|
||||
assertThat(interactor1mainScope1).isNotEqualTo(interactor2mainScope1)
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException::class)
|
||||
fun testUncaughtHandler() = runBlockingTest {
|
||||
val handler = TestCoroutineExceptionHandler()
|
||||
RibCoroutinesConfig.exceptionHandler = handler
|
||||
|
||||
val interactor = FakeInteractor<Presenter, Router<*>>()
|
||||
interactor.attach()
|
||||
|
||||
interactor.mainScope.launch {
|
||||
throw RuntimeException("mainScope failed")
|
||||
}
|
||||
handler.cleanupTestCoroutines()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user