Ir al contenido principal
Versión: 6.2 🚧

BlockHound

[Traducción Beta No Oficial]

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

La extensión Kotest BlockHound activa el soporte para BlockHound en corrutinas. Ayuda a detectar código bloqueante en hilos de corrutinas no bloqueantes, por ejemplo cuando se llama accidentalmente a una función de biblioteca de E/S bloqueante en un hilo de interfaz de usuario.

nota

Para usar esta extensión añade el módulo io.kotest:kotest-extensions-blockhound a la ruta de compilación de tus tests.

Primeros pasos

Registra la extensión BlockHound en tu clase de pruebas:

class BlockHoundSpecTest : FunSpec({
extension(BlockHound())

test("detects for spec") {
blockInNonBlockingContext()
}
})

La extensión BlockHound también puede registrarse por caso de prueba o a nivel de proyecto.

Si BlockHound está habilitado a nivel de proyecto o spec, puedes desactivarlo para una prueba individual:

   test("allow blocking").config(extensions = listOf(BlockHound(BlockHoundMode.DISABLED))) {
blockInNonBlockingContext()
}

También puedes cambiar el BlockHoundMode para una sección de código:

   test("allow blocking section") {
// ...
withBlockHoundMode(BlockHoundMode.DISABLED) {
blockInNonBlockingContext()
}
// ...
}

Detección

Las llamadas bloqueantes serán detectadas en hilos de corrutinas donde no se espera que bloqueen. Estos hilos son creados por el dispatcher predeterminado, como muestra este ejemplo:

private suspend fun blockInNonBlockingContext() {
withContext(Dispatchers.Default) {
@Suppress("BlockingMethodInNonBlockingContext")
Thread.sleep(2)
}
}

Por defecto, la extensión BlockHound producirá una excepción como esta cuando detecte una llamada bloqueante:

reactor.blockhound.BlockingOperationError: Blocking call! java.lang.Thread.sleep
at io.kotest.extensions.blockhound.KotestBlockHoundIntegration.applyTo$lambda-2$lambda-1(KotestBlockHoundIntegration.kt:27)
at reactor.blockhound.BlockHound$Builder.lambda$install$8(BlockHound.java:427)
at reactor.blockhound.BlockHoundRuntime.checkBlocking(BlockHoundRuntime.java:89)
at java.base/java.lang.Thread.sleep(Thread.java)
at io.kotest.extensions.blockhound.BlockHoundTestKt$blockInNonBlockingContext$2.invokeSuspend(BlockHoundTest.kt:17)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
nota

Al invocarlo como BlockHound(BlockHoundMode.PRINT), imprimirá las llamadas detectadas y continuará la prueba sin interrupciones.

Cuando se detecte una llamada bloqueante, puedes:

  • reemplazar la llamada por una no bloqueante (usando una biblioteca compatible con corrutinas), o

  • programar la corrutina llamante para que se ejecute en un hilo de E/S separado (por ejemplo mediante Dispatchers.IO), o

  • añadir una excepción si el bloqueo es inofensivo (ver más abajo).

Personalización

Para personalizar BlockHound, familiarízate con la documentación de BlockHound.

Las excepciones para llamadas bloqueantes consideradas inofensivas pueden añadirse mediante una clase BlockHoundIntegration separada como esta:

import reactor.blockhound.BlockHound
import reactor.blockhound.integration.BlockHoundIntegration

class MyBlockHoundIntegration : BlockHoundIntegration {
override fun applyTo(builder: BlockHound.Builder): Unit = with(builder) {
allowBlockingCallsInside("org.slf4j.LoggerFactory", "performInitialization")
}
}

Para permitir que BlockHound detecte y cargue automáticamente la integración, añade su nombre de clase completo en un archivo de configuración de proveedor de servicios: resources/META-INF/services/reactor.blockhound.integration.BlockHoundIntegration.