MockK: qué es, conceptos clave y sintaxis

Autor: IT Sectr Publicado: 2026-04-08 Tiempo de lectura: 8 min

MockK es un framework Kotlin-first para crear objetos mock, diseñado específicamente para el ecosistema de Kotlin teniendo en cuenta sus características lingüísticas: corrutinas, funciones de extensión, data class y sealed class. A diferencia de Mockito, que fue portado a Kotlin desde Java, MockK se diseñó originalmente para la sintaxis de Kotlin y no requiere complementos adicionales para trabajar con clases final. Según MockK.io, la biblioteca se utiliza en más del 40% de los proyectos Kotlin con pruebas unitarias.

Puntos clave

  • MockK — una biblioteca de mocking orientada a Kotlin con soporte para corrutinas y características del lenguaje.
  • mockk() — el método principal para crear un objeto mock, similar a Mockito.mock().
  • every { } — un bloque para configurar el comportamiento del mock (stubbing) de forma declarativa.
  • coEvery / coVerify — construcciones especiales para trabajar con funciones suspend de corrutinas.
  • Relaxed mock — un mock que devuelve valores predeterminados sin stubbing explícito.

¿Qué es MockK?

MockK es una biblioteca para crear objetos mock, escrita en Kotlin y optimizada para su sintaxis. Resuelve los mismos problemas que Mockito — aislar el código probado de las dependencias — pero lo hace utilizando construcciones específicas de Kotlin: lambdas, DSL, reified generics y funciones suspend.

La principal ventaja de MockK sobre las soluciones portadas es el soporte nativo de Kotlin. En Mockito, simular una clase final requiere opt-in (mockito-inline), y los métodos estáticos requieren mockStatic. MockK lo admite de forma predeterminada, ya que las clases de Kotlin son final por defecto, y la omisión de esta limitación está integrada en la arquitectura de la biblioteca.

La versión 1.13.12 (2024) es una versión estable que admite Kotlin 2.0, el compilador K2 y proyectos multiplataforma (KMP). MockK también funciona con Kotlin/Native y Kotlin/JS, lo que lo convierte en la única opción para proyectos KMP donde ni Mockito ni EasyMock son aplicables.

MockK está diseñado teniendo en cuenta las particularidades de Kotlin y utiliza las características del lenguaje — reified generics, DSL con lambdas, funciones inline — para proporcionar una API concisa y type-safe sin sacrificar el rendimiento.

Cómo funciona MockK

El mecanismo de MockK se basa en la instrumentación de bytecode a través de la biblioteca ByteBuddy (como Mockito), pero la envuelve en un DSL amigable con Kotlin. En lugar de cadenas when().thenReturn(), MockK utiliza bloques lambda every { } y coEvery { } que parecen una extensión natural del lenguaje. Internamente, MockK intercepta la llamada dentro de la lambda, analiza el método y los argumentos mediante reflexión y los compara con las reglas de stubbing registradas.

Sintaxis básica de MockK

El bloque every { mock.method() } returns value se lee como “cada vez que se llama al método, devolver el valor.” Esta sintaxis declarativa está más cerca del estilo Kotlin y elimina la confusión con el orden de los argumentos en when(). Gracias a los reified generics de Kotlin, el tipo de mock se infiere automáticamente sin especificar explícitamente la clase.

kotlin
val repository = mockk<UserRepository>()

// Stubbing: cada llamada a findById(1) devuelve el usuario
every { repository.findById(1) } returns User("Alice")

// Llamada y verificación
val result = repository.findById(1)
assertEquals("Alice", result.name)

Relaxed mock: menos código repetitivo

A diferencia de Mockito, donde cada método debe configurarse explícitamente, MockK admite relaxed mock — un mock que devuelve valores predeterminados “razonables” para cualquier método: una lista vacía para List, 0 para Int, una cadena vacía para String. Esto reduce drásticamente la cantidad de código de preparación.

kotlin
// Relaxed mock — todos los métodos devuelven valores predeterminados
val api = mockk<ApiService>(relaxed = true)

// No requiere stubbing — devuelve una lista vacía
println(api.getUsers()) // []

Creación de mocks y mocks relajados

MockK ofrece varias formas de crear objetos mock: mockk<T>() para mocks estrictos (cada método debe configurarse explícitamente), mockk<T>(relaxed = true) para mocks relajados y spyk(obj) para crear un espía sobre un objeto real.

FunciónTipoComportamiento sin stubbing
mockk()Mock estrictoLanza una excepción al llamar a un método sin stubbing
mockk(relaxed = true)Mock relajadoDevuelve el valor predeterminado
spyk()EspíaLlama al método real si no hay stub configurado
slot()Argument CaptorCaptura el argumento para verificación

La elección entre mock estricto y relajado depende del contexto. Un mock estricto garantiza que la prueba no utilice métodos cuyo comportamiento no esté definido — esto aumenta la fiabilidad. Un mock relajado es conveniente para la creación rápida de prototipos de pruebas donde no todas las dependencias son importantes. En la práctica, se recomienda comenzar con un mock estricto y cambiar a relajado solo cuando el stubbing ocupa más líneas que la prueba misma.

Stubbing: configuración del comportamiento con el bloque every

El bloque every es la construcción central de stubbing en MockK. Dentro de la lambda, se describe una llamada a un método con argumentos específicos, y luego se devuelve un valor mediante returns, se lanza una excepción mediante throws o se calcula una respuesta mediante answers.

Diferentes formas de stubbing

MockK admite todos los escenarios necesarios para las pruebas: devolver un valor, lanzar una excepción, calcular una respuesta basada en argumentos y múltiples respuestas en orden (secuencia de llamadas).

kotlin
// Devolver valor
every { repo.findById(1) } returns User("Alice")

// Lanzar excepción
every { repo.findById(999) } throws NotFoundException()

// Respuesta dinámica
every { repo.save(any()) } answers {
    val user = firstArg<User>()
    user.copy(id = 42)
}

// Secuencia de respuestas
every { repo.findAll() } returnsMany listOf(
    listOf(User("Alice")),
    listOf(User("Bob")),
    emptyList()
)

Verify y coVerify para corrutinas

Verify en MockK es similar a Mockito.verify() en propósito, pero utiliza DSL de Kotlin: verify { mock.method() }. Para funciones suspend se utiliza coVerify { mock.suspendMethod() }, que funciona correctamente con corrutinas y no requiere un ejecutor especial.

Verificación del número de llamadas

MockK admite los mismos modificadores que Mockito: exactly(1), atLeast(2), atMost(5), wasNot(Called). La sintaxis es minimalista — el modificador se pasa como primer argumento en verify { }.

kotlin
// Verificación: método llamado exactamente 1 vez
verify(exactly = 1) { repo.save(any()) }

// Verificar orden de llamadas
verifySequence {
    repo.save(any())
    repo.flush()
}

// coVerify para funciones suspend
coVerify { api.fetchUsers() }

Slot: captura de argumentos

Para la verificación de argumentos se utiliza slot() — un análogo de ArgumentCaptor. Un slot se declara antes de la llamada, se pasa a every o verify, y después de la ejecución de la prueba contiene el valor capturado.

kotlin
val userSlot = slot<User>()

verify { repo.save(capture(userSlot)) }

assertEquals("Alice", userSlot.captured.name)

Anotaciones de MockK e integración con JUnit

MockK proporciona las anotaciones @MockK y @RelaxedMockK para crear mocks mediante inicialización en JUnit 5. La extensión MockKExtension crea automáticamente mocks antes de cada prueba y los limpia después — similar a MockitoExtension, pero con soporte para modo relajado.

Ejemplo con MockKExtension

La anotación @InjectMockKs (o la alternativa @MockK con creación explícita de objetos) inyecta mocks en la instancia probada. Esto reduce el código repetitivo y hace que el código de la prueba sea más limpio.

kotlin
@ExtendWith(MockKExtension::class)
class UserServiceTest {

    @MockK
    lateinit var repository: UserRepository

    @InjectMockKs
    lateinit var service: UserService

    @Test
    fun `getUser returns user from repository`() {
        every { repository.findById(1) } returns User("Alice")
        assertEquals("Alice", service.getUser(1)?.name)
    }
}

MockK vs Mockito: qué elegir para Kotlin

La elección entre MockK y Mockito depende de la composición del equipo y del tipo de proyecto. Mockito tiene un ecosistema más grande, más ejemplos y más integraciones, pero MockK proporciona una sintaxis Kotlin más limpia y soporte nativo para las características del lenguaje. Para proyectos nuevos en Kotlin, se recomienda MockK como la solución más idiomática.

CriterioMockKMockito
SintaxisDSL de Kotlin (every, verify)Estilo Java (when, thenReturn)
CorrutinascoEvery, coVerify (nativo)Requiere bibliotecas adicionales
Clase finalAdmitido por defectoRequiere mockito-inline
KMPAdmitidoNo admitido
Relaxed mockIntegradoSin equivalente
PopularidadCreciente en la comunidad KotlinDomina en proyectos Java e híbridos

Para proyectos en Kotlin puro (sin clases Java), MockK es preferible: menos código repetitivo, soporte nativo de corrutinas, sin sorpresas con clases final. Para proyectos híbridos o equipos con experiencia en Java, Mockito sigue siendo una opción viable — ambas bibliotecas se pueden usar en el mismo proyecto a través de diferentes módulos. Al migrar de Mockito a MockK, basta con reemplazar las anotaciones @Mock por @MockK y reescribir los bloques when().thenReturn() al formato every { }.

Preguntas frecuentes

¿En qué se diferencia un relaxed mock de un mock normal en MockK?

Relaxed mock devuelve valores predeterminados para todos los métodos sin stubbing (lista vacía, 0, null) sin lanzar excepciones. Un mock normal (estricto) requiere stubbing explícito de cada método — de lo contrario, la prueba falla. El relaxed mock es conveniente para pruebas rápidas, el estricto para pruebas fiables.

¿Cómo simular funciones de extensión en MockK?

MockK admite la simulación de funciones de extensión a través de mockkStatic(). Esto es posible porque las funciones de extensión en Kotlin son métodos estáticos con el receptor como primer parámetro. Para cada función de extensión, debe especificar la clase en la que está declarada.

¿Funciona MockK con Kotlin Multiplatform?

Sí, MockK admite Kotlin Multiplatform (KMP) para código común. En las plataformas JVM, Native y JS, puede usar la API común: mockk(), every, verify. Esto hace que MockK sea la única opción para proyectos KMP donde Mockito no funciona.

¿Cómo verificar el orden de las llamadas en MockK?

Use verifySequence { } — un bloque donde las llamadas se especifican estrictamente en el orden esperado. Si el orden real difiere, verifySequence lanzará una excepción indicando la primera llamada que no coincide.

¿Se pueden usar MockK y Mockito en el mismo proyecto?

Sí, técnicamente es posible, pero no se recomienda. Pueden ocurrir conflictos a nivel de instrumentación de bytecode (ByteBuddy vs mockito-inline). Si un proyecto ya usa Mockito, la migración a MockK puede ser gradual mediante el aislamiento de módulos.

Resumen

  • MockK — una biblioteca de mocking Kotlin-first con soporte nativo del lenguaje.
  • every { } — un DSL declarativo para configurar el comportamiento de los mocks.
  • coEvery / coVerify — soporte para funciones suspend en corrutinas sin dependencias adicionales.
  • Relaxed mock — un mock con valores predeterminados que reduce el código repetitivo.
  • @MockK / @InjectMockKs — anotaciones para la creación automática de mocks en JUnit 5.
  • MockK vs Mockito — MockK es preferible para proyectos Kotlin puros y KMP.
  • verifySequence — verificación del orden estricto de las llamadas a métodos.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también