Mocking

Para mocking, Mockall Ă© uma biblioteca muito usada. VocĂȘ precisa refatorar seu cĂłdigo para usar traits, que vocĂȘ pode entĂŁo rapidamente "mockar":

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 Ă© a biblioteca de mocking recomendada para Android (AOSP). Existem outras bibliotecas de mocking disponĂ­veis em crates.io, em particular na ĂĄrea de mocking de serviços HTTP. As outras bibliotecas de mocking funcionam de maneira semelhante ao Mockall, o que significa que elas facilitam a obtenção de uma implementação de mock de um determinado trait.

  • Observe que o mocking Ă© um tanto controverso: mocks permitem que vocĂȘ isole completamente um teste de suas dependĂȘncias. O resultado imediato Ă© uma execução de teste mais rĂĄpida e estĂĄvel. Por outro lado, os mocks podem ser configurados incorretamente e retornar uma saĂ­da diferente daquela que as dependĂȘncias reais fariam.

    Se possĂ­vel, Ă© recomendĂĄvel que vocĂȘ use as dependĂȘncias reais. Como exemplo, muitos bancos de dados permitem que vocĂȘ configure um backend em memĂłria. Isso significa que vocĂȘ obtĂ©m o comportamento correto em seus testes, alĂ©m de serem rĂĄpidos e limparem automaticamente apĂłs si mesmos.

    Da mesma forma, muitos frameworks da web permitem que vocĂȘ inicie um servidor em processo que se vincula a uma porta aleatĂłria em localhost. Sempre prefira isso a mockar o framework pois isso ajuda vocĂȘ a testar seu cĂłdigo no ambiente real.

  • Mockall nĂŁo faz parte do playground do Rust, entĂŁo vocĂȘ precisa executar este exemplo em um ambiente local. Use cargo add mockall para adicionar rapidamente o Mockall a um projeto Cargo existente.

  • Mockall tem muito mais funcionalidades. Em particular, vocĂȘ pode configurar expectativas que dependem dos argumentos passados. Aqui usamos isso para "mockar" um gato que fica com fome 3 horas apĂłs a Ășltima vez que foi

#[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);
}
  • VocĂȘ pode usar .times(n) para limitar o nĂșmero de vezes que um mĂ©todo mock pode ser chamado para n --- o mock automaticamente irĂĄ gerar um pĂąnico quando descartado se isso nĂŁo for satisfeito.