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 usando double('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étodo start del objeto Car.

¿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 usando double('WeatherService').
  • Configuramos el stub para que el método fetch_weather devuelva 'Sunny'.
  • Verificamos que el método report del objeto WeatherReporter 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!

© Copyright 2024. Todos los derechos reservados