Solución:
Al ejecutar pruebas, por ejemplo, para ViewModel que inician corrutinas, es más probable que caiga en la siguiente excepción
java.lang.IllegalStateException: El módulo con el despachador principal no se pudo inicializar. Para las pruebas, se puede utilizar Dispatchers.setMain del módulo kotlinx-coroutines-test
La razón detrás de esto es la falta de Looper.getMainLooper()
en el entorno de prueba que está presente en una aplicación real. Para solucionar este problema, debe cambiar el despachador principal con TestCoroutineDispatcher
Asegúrese de tener una dependencia de prueba de rutina en su archivo Gradle
“org.jetbrains.kotlinx: kotlinx-coroutines-test: $ coroutine_version”
SOLUCION 1 – No escalable
Defina lo siguiente en su clase de prueba -> Anote su clase con @ExperimentalCoroutinesApi
val dispatcher = TestCoroutineDispatcher()
@Before
fun setup() {
Dispatchers.setMain(dispatcher)
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
Nota: también puede pasar Dispatchers.Main
como dependencia del constructor para sus repositorios como CoroutineDispatcher
en caso de que tenga uno. Se recomienda no codificar sus despachadores en repositorios / modelos de vista, etc. MIRE ESTO POR FAVOREEEEEEE
Por qué no escalable: deberá copiar y pegar el mismo código en cada clase de prueba
SOLUCION 2 – escalable [Use This – It is used by Google]
En esta solución, crea la regla personalizada. Agregue una clase de utilidad en su paquete de prueba
@ExperimentalCoroutinesApi
class MainCoroutineRule(
private val dispatcher: TestCoroutineDispatcher = TestCoroutineDispatcher()
) : TestWatcher(), TestCoroutineScope by TestCoroutineScope(dispatcher) {
override fun starting(description: Description?) {
super.starting(description)
Dispatchers.setMain(dispatcher)
}
override fun finished(description: Description?) {
super.finished(description)
cleanupTestCoroutines()
Dispatchers.resetMain()
}
}
Si desea explicaciones sobre la clase de utilidad anterior, consulte este CÓDIGO-LAB.
En su clase de prueba, simplemente agregue las siguientes líneas y estará listo para comenzar
@get:Rule
val coroutineRule = MainCoroutineRule()
Creo que puedes ver por qué esto es escalable si tienes muchas clases de prueba.
SOLUCIÓN 3 [I hope you don’t reach here]
También puedes usar Dispatchers.Unconfined
ENLACE
A coroutine dispatcher that is not confined to any specific thread. It executes the initial continuation of a coroutine in the current call-frame and lets the coroutine resume in whatever thread that is used by the corresponding suspending function, without mandating any specific threading policy. Nested coroutines launched in this dispatcher form an event-loop to avoid stack overflows
Puede agregarlo de la siguiente manera
@Before
fun setup() {
Dispatchers.setMain(Dispatchers.Unconfined)
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
Codificación feliz. . . .
No tienes acceso a Dispatchers. Principal en pruebas unitarias
Ver https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/
Dispatchers.Main Delegation
parte explica en detalle lo que debe hacer.
ahora puedes agregar esto a tu prueba:
Dispatchers.setMain(Dispatchers.Unconfined)
u otro despachador … es experimental pero obras!