Lightweight library allowing to mock functions in Rust
https://crates.io/crates/covers
2020-06-02: #[mock] now corectly removes function below from release build
2020-06-02: The crate now compiles with Rust 'stable' channel, so can be used in 'stable' projects
use covers::{mocked, mock};
#[mocked(mock_foo)]
fn foo(name: &str) -> String {
format!("Response: Foo = {}", name)
}
fn mock_foo(another_name: &str) -> String {
format!("Response: Mocked(Foo = {})", another_name)
}
#[mocked(module::mock_bar)]
fn bar(name: &str) -> String {
format!("Response: Bar = {}", name)
}
pub struct Struct {}
mod module {
use super::*;
#[mock]
pub fn mock_bar(name: &str) -> String {
let original_function_result = _bar(name);
format!("Response: Mocked({})", original_function_result)
}
pub fn yyy(this: Struct, name: &str) -> String {
format!("Response: Mocked({})", name)
}
}
impl Struct {
#[mocked(Struct::mock_baz, scope = impl)]
fn baz(name: &str) -> String {
format!("Response: Baz = {}", name)
}
fn mock_baz(name: &str) -> String {
format!("Response: Baz = {}", name)
}
#[mocked(module::yyy)]
fn xxx(self, name: &str) -> String {
format!("Response: Baz = {}", name)
}
}-
You can mock all types of functions with
#[mocked(mock_fn)]:- inline functions (including ones which are inside modules)
- struct functions (in this case you need to hint macro with
scope = impl) - struct variant functions (use
this: Structor_self: Structas the first argument instead ofself)
-
You can manually create and store mock functions:
- inline
- in separate modules (including
#[cfg(test)] mod tests {}) - in structs implementation blocks
-
scope = implhint is required for static struct functions / static methods -
There is no need in adding
scope = implstruct variant's function, it is set automatically for all functions with the first argumentself -
#[mock]let compiler know that this code should not be compiled for release builds.Otherwise, it makes related function
pub. You can disable this logic passingno-pubfor the crate'sfeatures -
Using
#[mock]is strictly required when we use reference to an original function inside. (Usually it is the same name function prepended by underscore_). Otherwise release build could fail. -
You can change a prefix of original function passing
features=["__"]orfeatures=["_orig_"]in[dependencies]block ofCargo.tomlforcoverscrate. One underscore is default -"_"
- Updated: If you relying on mocks calling
_original_function()in your tests you should be aware of:cargo test --releasecan lead to unexpected results or assertion errors - cause no#[cfg(debug_assertions)]enabled. Consider a test be reworked, narrow scope or avoid using original functions
NB: You can find lots of usage examples here - in the crate of integration tests.