En este tema, aprenderemos sobre dos técnicas fundamentales en las pruebas de software: Mocking y Stubbing. Estas técnicas son esenciales para aislar el código que estamos probando y simular comportamientos de dependencias externas.
¿Qué es Mocking?
Mocking es una técnica utilizada en las pruebas unitarias para simular el comportamiento de objetos reales. Los mocks permiten verificar que ciertas interacciones ocurren entre los objetos, como llamadas a métodos con parámetros específicos.
Ventajas del Mocking
- Aislamiento: Permite probar una unidad de código sin depender de otras partes del sistema.
- Control: Facilita la simulación de diferentes escenarios y comportamientos.
- Velocidad: Las pruebas son más rápidas porque no dependen de recursos externos como bases de datos o servicios web.
Ejemplo de Mocking en Ruby con RSpec
# Ejemplo de clase que queremos probar class Car def initialize(engine) @engine = engine end def start @engine.start end end # Prueba con Mocking RSpec.describe Car do it 'starts the engine' do engine = double('Engine') expect(engine).to receive(:start) car = Car.new(engine) car.start end end
En este ejemplo:
- Creamos un mock para la clase
Engine
usandodouble('Engine')
. - Configuramos una expectativa para que el método
start
sea llamado en el mock. - Verificamos que la llamada al método
start
ocurre cuando se llama al métodostart
del objetoCar
.
¿Qué es Stubbing?
Stubbing es una técnica utilizada para reemplazar el comportamiento de métodos o funciones con implementaciones predefinidas. Los stubs permiten simular respuestas de métodos sin ejecutar el código real.
Ventajas del Stubbing
- Simulación: Permite simular respuestas de métodos sin ejecutar el código real.
- Flexibilidad: Facilita la creación de diferentes escenarios de prueba.
- Independencia: Las pruebas no dependen de la implementación real de los métodos.
Ejemplo de Stubbing en Ruby con RSpec
# Ejemplo de clase que queremos probar class WeatherService def fetch_weather # Lógica para obtener el clima desde un servicio externo end end class WeatherReporter def initialize(service) @service = service end def report @service.fetch_weather end end # Prueba con Stubbing RSpec.describe WeatherReporter do it 'reports the weather' do service = double('WeatherService') allow(service).to receive(:fetch_weather).and_return('Sunny') reporter = WeatherReporter.new(service) expect(reporter.report).to eq('Sunny') end end
En este ejemplo:
- Creamos un stub para la clase
WeatherService
usandodouble('WeatherService')
. - Configuramos el stub para que el método
fetch_weather
devuelva'Sunny'
. - Verificamos que el método
report
del objetoWeatherReporter
devuelve'Sunny'
.
Ejercicio Práctico
Ejercicio 1: Mocking
Crea una clase BankAccount
con un método deposit(amount)
que llama a un método notify(amount)
de un objeto Notifier
. Escribe una prueba que verifique que el método notify
es llamado con el monto correcto.
# Clase BankAccount class BankAccount def initialize(notifier) @notifier = notifier end def deposit(amount) @notifier.notify(amount) end end # Prueba con Mocking RSpec.describe BankAccount do it 'notifies the deposit amount' do notifier = double('Notifier') expect(notifier).to receive(:notify).with(100) account = BankAccount.new(notifier) account.deposit(100) end end
Ejercicio 2: Stubbing
Crea una clase CurrencyConverter
con un método convert(amount, from_currency, to_currency)
que llama a un método get_exchange_rate(from_currency, to_currency)
de un objeto ExchangeRateService
. Escribe una prueba que simule diferentes tasas de cambio usando stubs.
# Clase CurrencyConverter class CurrencyConverter def initialize(service) @service = service end def convert(amount, from_currency, to_currency) rate = @service.get_exchange_rate(from_currency, to_currency) amount * rate end end # Prueba con Stubbing RSpec.describe CurrencyConverter do it 'converts currency using the exchange rate' do service = double('ExchangeRateService') allow(service).to receive(:get_exchange_rate).with('USD', 'EUR').and_return(0.85) converter = CurrencyConverter.new(service) expect(converter.convert(100, 'USD', 'EUR')).to eq(85) end end
Conclusión
En esta sección, hemos aprendido sobre las técnicas de Mocking y Stubbing en Ruby, utilizando RSpec. Estas técnicas son esenciales para escribir pruebas unitarias efectivas, permitiendo aislar el código bajo prueba y simular comportamientos de dependencias externas. Con la práctica, dominarás estas técnicas y podrás escribir pruebas más robustas y confiables.
En el siguiente módulo, profundizaremos en las mejores prácticas de estilo de código y convenciones en Ruby. ¡Sigue adelante!
Curso de Programación en Ruby
Módulo 1: Introducción a Ruby
Módulo 2: Conceptos Básicos de Ruby
Módulo 3: Trabajando con Colecciones
Módulo 4: Programación Orientada a Objetos en Ruby
- Clases y Objetos
- Variables y Métodos de Instancia
- Variables y Métodos de Clase
- Herencia
- Módulos y Mixins
Módulo 5: Conceptos Avanzados de Ruby
- Bloques, Procs y Lambdas
- Metaprogramación
- Manejo de Excepciones
- Entrada/Salida de Archivos
- Expresiones Regulares
Módulo 6: Introducción a Ruby on Rails
- ¿Qué es Ruby on Rails?
- Configuración del Entorno Rails
- Creando una Aplicación Simple en Rails
- Arquitectura MVC
- Enrutamiento
Módulo 7: Pruebas en Ruby
- Introducción a las Pruebas
- Pruebas Unitarias con Minitest
- Desarrollo Guiado por Comportamiento con RSpec
- Mocking y Stubbing
Módulo 8: Mejores Prácticas en Ruby
- Estilo de Código y Convenciones
- Refactorización
- Optimización del Rendimiento
- Mejores Prácticas de Seguridad