mockall para Rust: guia completo com exemplos práticos
1. O que é e para que serve
A biblioteca mockall é um poderoso framework para criar objetos mock (mock objects) automaticamente na linguagem Rust. Ela é voltada para testes unitários e permite que desenvolvedores isolem facilmente o código testado de dependências externas, como bancos de dados, clientes HTTP, sistemas de arquivos ou qualquer outro serviço. Diferente de escrever stubs de teste manualmente, o mockall gera automaticamente estruturas mock a partir de traits existentes, oferecendo uma API flexível para configurar expectativas (expectations) e verificar chamadas.
Por que isso é necessário? Em projetos reais, o código raramente existe no vácuo. Funções chamam outras funções, módulos dependem de bibliotecas externas. Ao testar um módulo específico, não queremos que o teste dependa do funcionamento do banco de dados ou da rede. O mockall resolve esse problema permitindo criar mocks que simulam o comportamento das dependências reais. Você pode definir o que um método deve retornar com determinados argumentos, quantas vezes ele deve ser chamado e até verificar a ordem das chamadas. Isso torna os testes rápidos, confiáveis e reproduzíveis.
A principal característica do mockall é a integração com o sistema de tipos do Rust e o funcionamento em tempo de compilação através do atributo #[automock]. Isso significa que os mocks são gerados automaticamente para qualquer trait, economizando muito tempo e reduzindo a quantidade de código boilerplate. A biblioteca suporta funções assíncronas, genéricos, traits com tipos associados e muito mais, tornando-se uma ferramenta indispensável para desenvolvimento sério em Rust.
2. Instalação
Para usar o mockall no seu projeto Rust, adicione a dependência no arquivo Cargo.toml. A biblioteca é instalada através do gerenciador de pacotes padrão Cargo. Recomenda-se adicioná-la apenas como dev-dependency, já que é usada exclusivamente para testes.
# Cargo.toml
[dev-dependencies]
mockall = "0.13" # Use a versão atual no momento da leitura
Após adicionar a linha, execute o comando cargo build ou cargo test para que o Cargo baixe e compile a biblioteca. Se você estiver trabalhando em um projeto que já possui outras dependências, verifique se a versão do mockall é compatível com a sua versão do Rust (geralmente é necessário Rust 1.70+). Para verificar a versão mais recente, visite crates.io/crates/mockall.
3. Guia rápido
Vamos criar um exemplo mínimo funcional. Suponha que temos um trait Greeter que queremos mockar em um teste. Com #[automock], obtemos automaticamente a estrutura MockGreeter.
// src/lib.rs
use mockall::automock;
#[automock]
pub trait Greeter {
fn greet(&self, name: &str) -> String;
}
pub fn run_greeter(greeter: &impl Greeter, name: &str) -> String {
greeter.greet(name)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_greeting() {
// Cria o mock
let mut mock = MockGreeter::new();
// Configura a expectativa: ao chamar greet("Alice") retornar "Olá, Alice!"
mock.expect_greet()
.with(predicate::eq("Alice"))
.returning(|name| format!("Olá, {}!", name));
// Chama a função sendo testada
let result = run_greeter(&mock, "Alice");
// Verifica o resultado
assert_eq!(result, "Olá, Alice!");
}
}
Execute o teste com o comando cargo test. Se tudo estiver configurado corretamente, o teste passará com sucesso.