I've just published Mockall[1]: a new mocking library. Mocking is a powerful testing technique: you create mock objects that implement the same interface as real object, but whose responses are controlled by the test code. It's a great way to unit test the middle of your stack, or to inject errors at any level. For example, the test code below injects an error, and discovers that query_and_capitalize
has insufficient error handling
use mockall::*;
use mockall::predicate::*;
use std::io::{Error, ErrorKind, Result};
#[automock]
trait Database {
fn query(&self, key: u32) -> Result<String>;
}
fn query_and_capitalize(db: &Database, key: u32) -> String {
db.query(key)
.unwrap() // No error handling!
.to_uppercase()
.to_string()
}
#[test]
fn query_error() {
let mut mock = MockDatabase::new();
mock.expect_query()
.with(eq(4))
.return_once(|_| Err(Error::from(ErrorKind::NotFound)));
assert_eq!("NOTFOUND", query_and_capitalize(&mock, 4));
}
Rust already has several mocking libraries, but Mockall has several powerful features that the others all lack:
- It can mock methods that return references
- It supports where clauses in all positions
- It can mock methods that use
-> impl Trait
return syntax - It can mock methods that return common
Deref
types like&str
without using cumbersome global constants. - Its mock objects can be passed between threads, even if some methods use argument or return types that aren't
Send
.
Enjoy! And please don't hesitate to open any issues, even for questions.
[1] Technically, I published it a month ago, but it took awhile to shake out some bugs.