Expand description
Mock any function types in Rust.
Make sure to only use this crate for testing purposes, as it will add a lot of overhead to your code.
.mock_once(..)
expects a closure that takes the arguments of the function and returns the same return type as the function.
§Basic Usage
On the function you want to mock, add the #[mock]
attribute.
#[cfg_attr(test, mockem::mock)]
fn foo() -> String {
format!("foo")
}
fn bar() -> String {
format!("Hello, {}!", foo())
}
#[test]
fn test_fn() {
use mockem::MockCall;
foo.mock_once(|| "mockem".to_owned());
foo.mock_once(|| "mockem2".to_owned());
assert_eq!(&bar(), "Hello, mockem!");
assert_eq!(&bar(), "Hello, mockem2!");
// works normally after all mocks are used
assert_eq!(&bar(), "Hello, foo!");
}
§Mocking Repeatedly
If you want to mock a function more than once or indefinitely, use mock_repeat
instead of mock_once
.
mock_repeat
takes an Option<usize>
as its first argument, which is the number of times to mock the function;
None
means to mock the function indefinitely.
#[cfg_attr(test, mockem::mock)]
fn foo(a: &str) -> String {
format!("{a}")
}
fn bar(a: &str) -> String {
format!("Hello, {}!", foo(a))
}
#[test]
fn test_fn() {
use mockem::{MockCall, ClearMocks};
foo.mock_repeat(None, |a| format!("mocked {a}"));
assert_eq!(&bar("bar"), "Hello, mocked bar!");
assert_eq!(&bar("foo"), "Hello, mocked foo!");
assert_eq!(&bar("baz"), "Hello, mocked baz!");
// this clears all mocks, which will stop the indefinite mock
foo.clear_mocks();
assert_eq!(&bar("baz"), "Hello, baz!");
}
§Impl Blocks
If you want to mock impl methods, add the #[mock]
attribute to the impl block.
Do the same for impl trait methods.
This will mock all methods in the impl block.
struct Foo;
#[cfg_attr(test, mockem::mock)]
impl Foo {
fn foo(&self) -> String {
format!("foo")
}
}
trait Baz {
fn baz(&self) -> String;
}
#[cfg_attr(test, mockem::mock)]
impl Baz for Foo {
fn baz(&self) -> String {
format!("baz")
}
}
fn bar() -> String {
format!("Hello, {} and {}!", Foo.foo(), Foo.baz())
}
#[test]
fn test_fn() {
use mockem::MockCall;
Foo::foo.mock_once(|_| "mockem".to_owned());
Foo::baz.mock_once(|_| "mockem2".to_owned());
assert_eq!(&bar(), "Hello, mockem and mockem2!");
}
§Async Functions
Async functions are also supported.
use async_trait::async_trait;
struct Foo;
#[cfg_attr(test, mockem::mock)]
impl Foo {
async fn foo(&self) -> String {
format!("foo")
}
}
#[async_trait]
trait Baz {
async fn baz(&self) -> String;
}
// also works with async_trait
// but you must place #[mock] above #[async_trait]
#[cfg_attr(test, mockem::mock)]
#[async_trait]
impl Baz for Foo {
async fn baz(&self) -> String {
format!("baz")
}
}
async fn bar() -> String {
format!("Hello, {} and {}!", Foo.foo().await, Foo.baz().await)
}
#[test]
fn test_fn() {
use mockem::MockCall;
Foo::foo.mock_once(|_| "mockem".to_owned());
Foo::baz.mock_once(|_| "mockem2".to_owned());
assert_eq!(&bar().await, "Hello, mockem and mockem2!");
}
Traits§
- Clear all mocked return values related to this function. You can use this if you have a recursive mock closure that continously mocks.
- Auto-implemented trait for mocking return values of functions.
Functions§
- Clear all mocks in the ThreadLocal; only necessary if tests share threads