https://github.com/craftytrickster/mock_me
TLDR: I made a (hopefully) easy way to mock functions when writing unit tests using procedural macros, I will include a code example at bottom of this post.
Recently, while I was working on a Rust webserver, I was frustrated by the lack of an easy way to mock functions (mainly db calls) when writing unit tests.
Eventually, I settled on a somewhat unsatisfying and unstructured approach using adhoc conditional compilation, as I have documented here Artisanal Mocks.
I have made this crate in order to make this whole process easier, hopefully you like it. I feel that it provides an unmet need for testing Rust code. Here is the code example on how to use it from the readme:
#![feature(proc_macro)]
extern crate mockme;
use mockme::{mock, inject};
// Below we will create two mocking identifiers called id_1 and id_2.
// We will then provide the name of the two functions we are mocking, as well as
// their type signature. In future iterations, hopefully the signature won't be needed.
#[mock(id_1="external_db_call: fn(u32) -> String", id_2="other_call: fn() -> String")]
fn my_super_cool_function() -> String {
let input = 42u32;
// external_db_call will be replaced with fake_mocked_call during testing
let db_result = external_db_call(input);
// other_call will also be replaced
let other_result = other_call();
format!("I have two results! {} and {}", db_result, other_result)
}
// Finally, when we run our tests, we simply need to provide the identifier we previously used,
// as well as the name of the replacement function
#[test]
#[inject(id_1="db_fake", id_2="other_fake")]
fn actual_test2() {
let result = my_super_cool_function();
assert_eq!(result, "I have two results! Faker! and This is indeed a disturbing universe.");
}
fn db_fake(_: u32) -> String { "Faker!".to_string() }
fn other_fake() -> String { "This is indeed a disturbing universe.".to_string() }
This library is still a work in progress, so I would appreciate any feedback and/or contributions. I do not consider myself a Rust expert, so I am sure there are ways to improve what I did.
Also, fun bonus trivia fact: this is the first time that I have really needed to use an unsafe block in my code.