Test Doubles — qué son, tipos de sustitutos y aplicación

Autor: IT Sectr Publicado: 2026-04-10 Tiempo de lectura: 9 min

Los Test Doubles son objetos sustitutos utilizados en las pruebas unitarias en lugar de dependencias reales. El término fue introducido por Gerard Meszaros en el libro “xUnit Test Patterns” (2007) como un concepto general para Mock, Stub, Fake, Spy y Dummy. Según Martin Fowler (2024), los Test Doubles permiten aislar el componente bajo prueba de su entorno, haciendo que las pruebas sean deterministas, rápidas e independientes de servicios externos.

Puntos clave

  • Test Doubles — término general para todos los tipos de objetos sustitutos en pruebas
  • Mock verifica la interacción: qué métodos se llamaron y con qué argumentos
  • Stub devuelve valores predefinidos sin verificar llamadas
  • Fake — implementación funcional simplificada (ej., base de datos en memoria)
  • Spy registra llamadas para su verificación posterior, Dummy llena parámetros

¿Qué son los Test Doubles?

Test Doubles es un término de la industria automotriz (dobles de riesgo), trasladado al desarrollo de software. Así como un doble de riesgo reemplaza a un actor en una escena peligrosa, un Test Double reemplaza un componente real en un escenario de prueba. Esto es necesario cuando la dependencia real no está disponible, es lenta, no determinista o tiene efectos secundarios.

El concepto de Test Double abarca cinco tipos específicos, cada uno resolviendo su propia tarea. La tipología de Meszaros es canónica y se utiliza en todas las guías modernas de pruebas. La diferencia entre los tipos radica en el grado de control y verificación: desde el simple llenado de parámetros (Dummy) hasta la verificación completa de secuencia de llamadas (Mock).

Por qué se necesitan los Test Doubles

El propósito principal de los Test Doubles es aislar el módulo bajo prueba. En el desarrollo móvil, las dependencias reales incluyen servidores API, bases de datos, sistemas de archivos, sensores del dispositivo y servicios del sistema (LocationManager, Camera, Bluetooth). Usar estos componentes directamente hace que las pruebas sean lentas, frágiles y dependientes del entorno. Según Google Testing Blog (2023), las pruebas unitarias bien aisladas se ejecutan en milisegundos, mientras que las pruebas de integración se ejecutan en segundos y minutos.

Cinco tipos de Test Doubles

La clasificación de Gerard Meszaros incluye cinco tipos de Test Doubles, que se diferencian en comportamiento y propósito. Comprender la diferencia entre ellos es la base de las pruebas unitarias competentes.

Dummy

Dummy es un objeto que se pasa al método bajo prueba pero nunca se utiliza. Dummy solo es necesario para satisfacer la firma del método. En Kotlin, esto suele ser null, emptyList() o un objeto con stubs. Dummy no debe contener ninguna lógica — si se llama, la prueba debe fallar.

Fake

Fake es una implementación simplificada pero funcional de una interfaz. A diferencia de Mock y Stub, Fake contiene lógica de negocio real, pero en forma simplificada. Un ejemplo clásico es InMemoryUserRepository, que almacena datos en un HashMap en lugar de una base de datos. Fake se usa cuando se necesita probar lógica que depende del estado, pero sin la sobrecarga de la infraestructura real.

TipoPropósitoEjemplo
DummyLlenar un parámetronull, objeto vacío
FakeImplementación simplificada funcionalInMemoryRepository
StubDevolver un valor fijowhen(api.getUser()).thenReturn(user)
SpyRegistrar llamadas para verificaciónverify(spy).save(user)
MockVerificar interacciónverify(mock).sendEmail(email)

Stub

Stub devuelve valores predefinidos para llamadas específicas. Stub no verifica si fue llamado — simplemente proporciona datos. En Mockito, Stub se crea mediante when(method).thenReturn(value). Stub es ideal para pruebas cuando se necesita que una dependencia devuelva un valor específico, pero el hecho de la llamada en sí no es importante.

Spy

Spy es un envoltorio alrededor de un objeto real que registra todas las llamadas para su verificación posterior. A diferencia de Mock, Spy delega las llamadas al objeto real pero permite verificar que ocurrieron. En Mockito, Spy se crea mediante spy(realObject). Spy es útil para mocking parcial, cuando se quiere usar un objeto real pero verificar algunas llamadas.

Mock

Mock es un objeto con expectativas de llamada predefinidas. Mock verifica que métodos específicos fueron llamados con argumentos específicos y en un orden específico. A diferencia de Stub, Mock se centra en la verificación de comportamiento en lugar de la devolución de datos. Mock es el tipo de Test Double más potente y más utilizado en el desarrollo móvil.

Mock vs Stub: diferencias clave

La diferencia entre Mock y Stub a menudo causa confusión incluso entre desarrolladores experimentados. La principal diferencia está en el propósito: Stub verifica el estado (state verification), Mock verifica el comportamiento (behavior verification).

Stub responde a la pregunta: “¿devolvió el código el resultado correcto?”. Mock responde a la pregunta: “¿llamó el código a los métodos correctos con los argumentos correctos?”. En el desarrollo móvil, Stub se usa cuando el importa el resultado (ej., datos de un repositorio), mientras que Mock se usa cuando importan los efectos secundarios (ej., enviar correo electrónico, escribir en una base de datos).

kotlin
// Stub: verificación de estado
every { repository.getUsers() } returns listOf(user)
val result = useCase.getUsers()
assertEquals(1, result.size)

// Mock: verificación de comportamiento
every { analytics.logEvent("purchase") } returns Unit
useCase.purchase(item)
verify { analytics.logEvent("purchase") }

Ejemplos de Test Doubles en Kotlin

Ejemplos prácticos de los cinco tipos de Test Doubles en Kotlin usando MockK — la biblioteca de mocking más popular para proyectos Android.

Fake: InMemoryUserRepository

kotlin
class InMemoryUserRepository : UserRepository {
    private val store = mutableMapOf<String, User>()

    override fun save(user: User) {
        store[user.email] = user
    }

    override fun findByEmail(email: String): User? {
        return store[email]
    }
}

Stub + Mock: prueba de UseCase

kotlin
class RegisterUseCaseTest {
    private val api = mockk<AuthApi>()
    private val repo = spyk(InMemoryUserRepository())
    private val useCase = RegisterUseCase(api, repo)

    fun `register user successfully`() = runTest {
        // Stub: devolver respuesta fija de API
        coEvery { api.register("test@test.com") } returns AuthResult.Success("token123")

        val result = useCase.execute("test@test.com")

        // Verify: verificar que el usuario se guardó
        verify { repo.save(any()) }
        assertTrue(result.isSuccess())
    }
}

Dummy: prueba con parámetro no utilizado

kotlin
data class Logger(val appContext: Context, val format: FormatType)

fun `test logger with dummy context`() {
    // Dummy: Context no se usa dentro de Logger
    val dummyContext = mockk<Context>()
    val logger = Logger(dummyContext, FormatType.JSON)
    assertEquals(FormatType.JSON, logger.format)
}

Cuándo usar cada tipo en desarrollo móvil

La elección del tipo de Test Double depende de qué se está probando exactamente: estado, comportamiento o integración. En el desarrollo móvil para Android e iOS, se han establecido las siguientes recomendaciones.

Para ViewModel y UseCase

Al probar ViewModel, use Mock para dependencias que producen efectos secundarios (repositorios, analíticas, navegación) y Stub para dependencias que devuelven datos (clientes API, ContentProvider). Esto permite verificar que el ViewModel maneja correctamente tanto los escenarios exitosos como los de error.

Para Repository y capa de datos

A nivel de Repository, prefiera Fake (implementaciones de base de datos en memoria) y Stub (respuestas fijas de API). Fake permite probar la lógica de almacenamiento en caché y el modo sin conexión sin configurar SQLite. Stub simula varios estados HTTP: 200, 404, 500, timeout.

  • Pruebas unitarias de lógica de negocio — Mock para todas las dependencias externas, Dummy para parámetros no utilizados
  • Pruebas de integración — Fake en lugar de Mock (verificar que los componentes funcionan juntos)
  • Pruebas de UI — Stub para respuestas API (mediante MockWebServer o WireMock)
  • Pruebas de caché — Fake para base de datos (en memoria en lugar de Room/SQLite)
  • Pruebas de asincronía — Mock con soporte de corrutinas (MockK + Turbine para Flow)

Errores comunes al usar sustitutos

El uso incorrecto de Test Doubles es una de las causas más comunes de pruebas frágiles que se rompen con cada refactorización.

Over-mocking: uso excesivo de Mock

El error más común es mockearlo todo. Si cada dependencia en una prueba se reemplaza con un Mock, la prueba deja de verificar el comportamiento real. Mock solo debe usarse para dependencias externas (red, base de datos, sistema de archivos, servicios del sistema). Los componentes internos de la aplicación (Value Object, data class, utilidades simples) no deben reemplazarse.

Under-specification: especificación insuficiente

El segundo error es crear un Mock sin definir expectativas. Si se llama a un método sin every / when, Mock devuelve un valor predeterminado (null, 0, false). Esto puede llevar a pruebas falsas positivas, donde Mock devuelve silenciosamente null y la prueba interpreta esto como un comportamiento correcto.

Over-verification: verificación excesiva

El tercer error es verificar cada llamada de cada Mock. Verify solo debe usarse para llamadas que son críticamente importantes desde la perspectiva de la lógica de negocio. La verificación excesiva hace que las pruebas sean frágiles: cambiar el orden de las llamadas en el código de producción rompe las pruebas sin cambiar el comportamiento.

Preguntas frecuentes

¿Cuál es la diferencia entre Mock y Stub?

Stub devuelve datos y verifica el estado (qué se devolvió), mientras que Mock verifica el comportamiento (qué métodos se llamaron). Stub = “devuelve X”, Mock = “verifica que se llamó a Y con el argumento Z”. En las pruebas reales, un mismo objeto a menudo actúa como Stub y Mock simultáneamente.

¿Cuándo usar Fake en lugar de Mock?

Fake es preferible a Mock cuando se prueba lógica que depende del estado: almacenamiento en caché, modo sin conexión, transacciones. Fake (implementación en memoria) permite probar estos escenarios sin llamadas verify frágiles. Mock es más adecuado para verificar el envío de datos: analíticas, push, email.

¿Qué biblioteca de Test Doubles es mejor para Android?

Para proyectos Android en Kotlin, se recomienda MockK. Admite corrutinas, funciones suspend, clases selladas y funciones de extensión sin configuración adicional. Para proyectos Java, Mockito sigue siendo el estándar — la biblioteca más popular con documentación extensa.

¿Cómo probar Kotlin Flow con Test Doubles?

Para probar Kotlin Flow, use la biblioteca Turbine junto con MockK. Turbine simplifica la verificación de emisiones de Flow: puede verificar el orden de los valores, la finalización del flujo y las excepciones. Stub para Flow devuelve flowOf(value), Mock verifica que se recolectó el Flow.

¿Es aceptable usar Test Doubles en pruebas de UI?

Sí, pero a nivel de respuestas API, no de componentes de UI. Las bibliotecas MockWebServer (OkHttp) y WireMock permiten simular respuestas HTTP en pruebas de UI. Los componentes de UI en sí (Compose, SwiftUI Views) no deben reemplazarse — su comportamiento se prueba mediante pruebas de captura de pantalla y Espresso.

Resumen

  • Test Doubles — término general para cinco tipos de objetos sustitutos: Mock, Stub, Fake, Spy, Dummy
  • Mock verifica el comportamiento (verify), Stub devuelve datos (thenReturn), Fake funciona como una implementación real simplificada
  • Spy envuelve un objeto real y registra llamadas, Dummy llena parámetros no utilizados
  • La tipología de Gerard Meszaros es la clasificación canónica utilizada en todos los frameworks modernos de mocking
  • Para proyectos Kotlin se recomienda MockK, para Java — Mockito, para iOS — Cuckoo u OHHTTPStubs
  • Errores comunes: over-mocking (reemplazar todo), under-specification (expectativas indefinidas), over-verification (verify excesivo)
  • Fake es preferible a Mock al probar lógica con estado — almacenamiento en caché, modo sin conexión y transacciones

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