Simulaciones

Mockall es una biblioteca que se usa para hacer simulaciones. Debes refactorizar tu código para usar traits, con los que podrás hacer simulaciones:

use std::time::Duration;

#[mockall::automock]
pub trait Pet {
    fn is_hungry(&self, since_last_meal: Duration) -> bool;
}

#[test]
fn test_robot_dog() {
    let mut mock_dog = MockPet::new();
    mock_dog.expect_is_hungry().return_const(true);
    assert_eq!(mock_dog.is_hungry(Duration::from_secs(10)), true);
}
This slide should take about 5 minutes.
  • Mockall is the recommended mocking library in Android (AOSP). There are other mocking libraries available on crates.io, in particular in the area of mocking HTTP services. The other mocking libraries work in a similar fashion as Mockall, meaning that they make it easy to get a mock implementation of a given trait.

  • Ten en cuenta que las simulaciones son algo polémicas, ya que te permiten aislar por completo una prueba de sus dependencias. El resultado inmediato es una ejecución de pruebas más rápida y estable. Por otro lado, las simulaciones se pueden configurar de forma incorrecta y devuelven un resultado diferente del que se obtendría con las dependencias reales.

    Si es posible, te recomendamos que uses las dependencias reales. Por ejemplo, muchas bases de datos te permiten configurar un backend en la memoria. Es decir, en tus pruebas obtendrás el comportamiento correcto y, además, son rápidas y se limpiarán de forma automática tras las pruebas.

    Del mismo modo, muchos frameworks web te permiten iniciar un servidor en proceso que se vincula a un puerto aleatorio en localhost. Siempre es mejor utilizar esta opción en lugar de simular el framework, ya que te ayuda a hacer pruebas con el código en el entorno real.

  • Mockall no forma parte de Rust Playground, por lo que debes ejecutar este ejemplo en un entorno local. Usa cargo add modelall para añadir de forma rápida Mockall a un proyecto de Cargo.

  • Mockall tiene muchas más funciones. En concreto, puedes configurar expectativas en función de los argumentos. Aquí utilizamos el ejemplo para simular un gato que tiene hambre 3 horas después de que le hayan dado de comer:

#[test]
fn test_robot_cat() {
    let mut mock_cat = MockPet::new();
    mock_cat
        .expect_is_hungry()
        .with(mockall::predicate::gt(Duration::from_secs(3 * 3600)))
        .return_const(true);
    mock_cat.expect_is_hungry().return_const(false);
    assert_eq!(mock_cat.is_hungry(Duration::from_secs(1 * 3600)), false);
    assert_eq!(mock_cat.is_hungry(Duration::from_secs(5 * 3600)), true);
}
  • Puedes utilizar .times(n) para limitar el número de veces que se puede llamar a un método de simulación a n. Si no se cumple, la simulación activará un pánico automáticamente cuando se elimine.