Stub: qué es, tipos y uso en testing

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

Stub (stub, doble de prueba) — un objeto de prueba que devuelve respuestas predefinidas a llamadas de métodos en lugar de una implementación real. En el desarrollo móvil, los stubs aíslan el módulo probado de las solicitudes de red, bases de datos y sistemas de archivos, permitiendo verificar la lógica sin configuración del entorno. A diferencia de mock, stub no verifica el comportamiento — solo proporciona datos. Más detalles en el artículo de Martin Fowler sobre test doubles.

Puntos clave

  • Stub — un doble de prueba que devuelve valores predefinidos en llamadas a métodos sin lógica
  • Aislamiento — los stubs desactivan dependencias reales: API, BD, archivos, sensores
  • Diferencia de Mock — stub no verifica llamadas, solo sustituye la respuesta
  • Android — MockWebServer (OkHttp) como stub para HTTP, MockK.constantAnswer para Kotlin
  • iOS — OCMock y protocolos de Swift con implementaciones de prueba como stubs

¿Qué es un Stub y en qué se diferencia de otros test doubles?

Stub es un objeto doble de prueba que reemplaza una dependencia real en un test y devuelve valores predefinidos para llamadas específicas. El término fue introducido en la clasificación de Gerard Meszaros (2007) en el libro «xUnit Test Patterns». Stub pertenece a la categoría de test doubles — objetos que sustituyen componentes reales durante las pruebas. El propósito principal de un stub es proporcionar a la unidad bajo prueba datos predecibles, eliminando la incertidumbre de los sistemas externos.

Cómo funciona — el test configura el stub antes de la ejecución: «cuando se llame al método getUsers(), devuelve esta lista de usuarios». Stub no contiene lógica de negocio, no verifica el orden de las llamadas ni registra el historial. Simplemente se coloca en lugar del componente real y devuelve lo que se le indicó. En el contexto de pruebas de Android, esto significa: el cliente OkHttp no hace una solicitud real al servidor, sino que recibe una respuesta de MockWebServer configurado como stub.

  • Stub — devuelve datos, no verifica llamadas
  • Mock — devuelve datos y verifica comportamiento (verify)
  • Fake — implementación simplificada funcional con lógica real
  • Spy — envuelve un objeto real, registrando llamadas
  • Dummy — se pasa pero no se usa (null, objeto vacío)

Cuándo usarlos — los stubs son óptimos para probar la capa de UI (ViewModel, Presenter) y la lógica de negocio (UseCase, Interactor), donde se necesita verificar la reacción a datos específicos: lista vacía, el servidor devolvió error 500, token expirado. Cualquier caso donde el test requiera un estado de entrada específico es tarea para stub. Cada escenario de prueba tiene su propia configuración de stub, lo que hace que las pruebas sean legibles y predecibles.

Clasificación de test doubles según Meszaros

Gerard Meszaros (2007) en el libro «xUnit Test Patterns» identificó cinco tipos de test doubles: dummy, stub, spy, mock, fake. Cada tipo cumple su función. Dummy — se pasa pero no se usa. Stub — devuelve datos. Spy — registra llamadas. Mock — verifica comportamiento. Fake — contiene lógica simplificada. Comprender esta clasificación ayuda al desarrollador a elegir la herramienta correcta para cada escenario de prueba.

¿Dónde se usan los stubs en pruebas de aplicaciones móviles?

Stubs para solicitudes de red

Solicitudes de red — el escenario más común para usar stubs. La aplicación hace llamadas HTTP a la API, y el test necesita verificar la reacción a diferentes respuestas: JSON exitoso, error 401 (no autorizado), tiempo de espera agotado, array vacío. MockWebServer (OkHttp) en Android y URLProtocol (iOS) actúan como stubs, devolviendo respuestas HTTP predefinidas sin conexión real al servidor. Esto acelera las pruebas de segundos a milisegundos.

Base de datos — Room (Android) y CoreData (iOS) tienen variantes en memoria, pero su configuración aún requiere tiempo. Stub en lugar del repositorio devuelve listas de Entity preparadas previamente sin tocar la BD. Esto es especialmente efectivo para probar ViewModel, donde se necesita verificar ordenamiento, filtrado o transformación de datos. La prueba se ejecuta en milisegundos independientemente del volumen de datos.

Servicios del sistema — LocationManager, SensorManager, SharedPreferences requieren un dispositivo real o emulador. Stub para LocationProvider devuelve coordenadas predefinidas, para SensorManager — valores fijos del acelerómetro. En iOS, el equivalente es CLLocationManager con una implementación de delegado de prueba. Sin stubs, estas pruebas requieren un dispositivo físico con condiciones específicas.

Sistema de archivos y caché — carga de imágenes, almacenamiento en caché de respuestas, trabajo con archivos de configuración — todas estas operaciones dependen del estado del disco. Stub para FileManager o ImageCache devuelve éxito/error sin leer archivos reales. Esto elimina fallos falsos en pruebas debido a discrepancias de rutas o permisos de acceso en diferentes máquinas de desarrollo.

Stub vs Mock vs Fake: diferencias clave

División de responsabilidades — tres tipos de test doubles resuelven diferentes tareas. Stub: «dame datos». Mock: «verifica que fui llamado». Fake: «funciono como el real, solo que más simple». La diferencia es crítica para la legibilidad de las pruebas: si un test usa mock donde se necesita stub, está sobrecargado de llamadas verify no relacionadas con el escenario probado.

CaracterísticaStubMockFake
PropósitoProporcionar datosVerificar interacciónImplementación simplificada
LógicaNoNoSí (pero simplificada)
VerificaciónNoSí (verify)Indirecta (mediante estado)
FlexibilidadBaja — respuestas fijasMediaAlta — la lógica se adapta
VelocidadMáximaAltaMedia
EjemploMockWebServer devuelve JSONMockito.verify(repository).save()InMemoryRepository con HashMap

Regla práctica — si el test verifica qué datos recibió el componente bajo prueba — usa stub. Si el test verifica si el componente llamó al método de la dependencia con los argumentos correctos — usa mock. Si simplemente quieres reemplazar una BD por una tabla hash — eso es fake. Mezclar tipos en un mismo test lo vuelve frágil: al cambiar la implementación, tendrás que reescribir tanto la lógica de stub como de verify.

Antipatrón: Stub con verify

Stub con verify — un error común donde el desarrollador configura un stub y luego añade verify(stub).method(). Stub por definición no debe ser verificado — para ello está mock. Si necesitas comprobar que se llamó a un método con argumentos específicos, usa Mockito.mock() en lugar de Mockito.stub(). Esta separación mantiene la intención del test clara para otros desarrolladores.

Implementación de stubs en Android con MockWebServer y MockK

MockWebServer — una librería de OkHttp para crear stubs HTTP en Android y JVM. Inicia un servidor HTTP local en un puerto especificado que intercepta las solicitudes del cliente OkHttp y devuelve respuestas predefinidas. La configuración toma tres líneas: crear el servidor, enqueue la respuesta, iniciarlo. El test puede encolar secuencialmente múltiples respuestas para escenarios con paginación o reintentos.

kotlin
class UserRepositoryTest {

    private val server = MockWebServer()

    fun setup() {
        server.start(8080)
        val client = OkHttpClient.Builder()
            .readTimeout(1, TimeUnit.SECONDS)
            .build()
    }

    fun test_user_list_success() {
        val json = "[{\"id\":1,\"name\":\"Alice\"}]"
        server.enqueue(MockResponse()
            .setBody(json)
            .setResponseCode(200)
        )
        val result = repository.getUsers()
        assertEquals(1, result.size)
    }

    fun teardown() {
        server.shutdown()
    }
}

MockK — una alternativa a Mockito para Kotlin con soporte de primera clase para corrutinas, funciones de extensión y clases selladas. Los stubs en MockK se crean mediante coEvery (para funciones suspend) y every (para funciones regulares). A diferencia de MockWebServer, MockK stub métodos de dependencia individuales en lugar de toda la capa HTTP. Esto es útil para pruebas unitarias de UseCase o Interactor, donde las dependencias son abstracciones de repositorios.

kotlin
interface UserRepository {
    suspend fun getUsers(): List<User>
}

class GetUsersUseCaseTest {

    private val repo = mockk<UserRepository>()

    private val useCase = GetUsersUseCase(repo)

    fun test_empty_list() = runTest {
        coEvery { repo.getUsers() } returns emptyList()

        val result = useCase.invoke()

        assertTrue(result.isEmpty())
        coVerify(exactly = 1) { repo.getUsers() }
    }
}

Mejores prácticas — para pruebas de integración usa MockWebServer (intercepta HTTP real), para pruebas unitarias usa MockK (stub interfaces). No stubees lo que no estás probando: si el test verifica el Repository, no stubees el cliente OkHttp dentro de él — usa un MockWebServer real a nivel HTTP. Esta regla mantiene las pruebas relevantes y reduce la fragilidad durante la refactorización.

Implementación de stubs en iOS con OCMock y protocolos

Protocolos de Swift como stubs — en el enfoque nativo de iOS, el stub se implementa mediante la sustitución de una estructura de prueba que cumple con el protocolo de la dependencia. En lugar de un NetworkService real, el test recibe un StubNetworkService que devuelve datos fijos. Swift es un lenguaje con tipado estático, por lo que el stub debe cumplir con el mismo protocolo que el servicio real. El compilador garantiza que el stub implemente todos los métodos requeridos.

swift
protocol NetworkServiceProtocol {
    func fetchUsers() async throws -> [User]
}

struct StubNetworkService: NetworkServiceProtocol {
    let result: Result<[User], Error>

    func fetchUsers() async throws -> [User] {
        try result.get()
    }
}

final class UsersViewModelTests: XCTestCase {
    func test_success_state() async {
        let stub = StubNetworkService(
            result: .success([User(name: "Alice")])
        )
        let vm = UsersViewModel(service: stub)
        await vm.load()
        XCTAssertEqual(vm.users.count, 1)
    }
}

OCMock para Objective-C — una librería para crear stubs y mocks en proyectos iOS legacy. OCMock admite métodos stub con argumentos y valores de retorno. Los proyectos modernos en Swift prefieren un enfoque basado en protocolos con stubs manuales — esto da control sobre cada método y no requiere dependencias externas. OCMock sigue siendo una opción para proyectos donde protocolizar todas las dependencias no es económicamente viable.

URLProtocol para stubs HTTP — un mecanismo del sistema en iOS para interceptar solicitudes de red mediante una subclase de URLProtocol. El test registra un URLProtocol personalizado que intercepta URLSession y devuelve respuestas stub. La ventaja sobre los stubs manuales: no es necesario cambiar la arquitectura de la aplicación — URLSession sigue siendo real, pero los datos se sustituyen a nivel de protocolo. La desventaja: es más difícil de depurar que un servicio stub explícito.

Preguntas frecuentes

¿En qué se diferencia Stub de Mock?

Stub devuelve datos predefinidos y no verifica si ocurrió una llamada. Mock adicionalmente verifica que el método fue llamado con los argumentos correctos (verify). Stub responde a la pregunta «qué devolver», Mock responde a «se hizo la llamada». Usa stub para verificación de estado, mock para verificación de interacción.

¿Cuándo usar Fake en lugar de Stub?

Fake es necesario cuando el test requiere una implementación funcional (aunque simplificada) — por ejemplo, una base de datos en memoria en lugar de Room. Stub es adecuado para escenarios únicos con datos predefinidos. Si repites el mismo stub en 10 pruebas — probablemente necesitas un Fake. Fake reduce la duplicación porque la lógica vive en una sola clase.

¿Se pueden stubear métodos estáticos?

En Android — MockK para objetos de Kotlin (object) soporta mockkObject(), incluyendo métodos estáticos de clases Java mediante mockkStatic(). En iOS — los métodos estáticos de Swift no se pueden stubear directamente; usa protocolos e DI para reemplazar una llamada static por un método de instancia de un protocolo. Los stubs estáticos son deuda técnica y deben evitarse en código nuevo.

¿Cómo stubear solicitudes de red en Android?

Usa MockWebServer (OkHttp) — funciona como un servidor HTTP local que encola respuestas. Para Retrofit, simplemente reemplaza la URL base por localhost:8080. Para Ktor, usa MockEngine — un mecanismo integrado para sustituir HttpStatement. Ambos enfoques funcionan sin internet real y dan control total sobre el código de estado, el cuerpo y los encabezados de la respuesta.

Stub vs Spy — ¿cuál es la diferencia?

Spy envuelve un objeto real y registra llamadas, mientras que Stub reemplaza completamente el objeto con respuestas fijas. Spy permite el uso parcial de la implementación real (otros métodos funcionan como están), mientras que stub no. Si necesitas verificar que se llamó a un método pero parte de la lógica debe ejecutarse — usa spy, no stub.

Resumen

  • Stub — un doble de prueba que devuelve respuestas predefinidas a llamadas de métodos durante las pruebas
  • Aislamiento de dependencias — los stubs reemplazan solicitudes de red, BD, servicios del sistema y sistema de archivos
  • Diferencia de Mock — stub no verifica llamadas, solo devuelve datos sin comprobación de comportamiento
  • Herramientas Android — MockWebServer para HTTP, MockK para interfaces de Kotlin con soporte de corrutinas
  • Herramientas iOS — stubs basados en protocolos en Swift, URLProtocol para HTTP, OCMock para Objective-C
  • No mezcles roles — no añadas verify a stub, usa mock para verificación de llamadas
  • Stub + MockWebServer — enfoque estándar para pruebas de integración sin servidor real

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