Crates.io | mockem |
lib.rs | mockem |
version | 0.2.4 |
source | src |
created_at | 2024-01-03 02:32:43.037643 |
updated_at | 2024-06-22 03:43:36.010032 |
description | mock'em functions! |
homepage | |
repository | https://github.com/poonesnerfect/mockem |
max_upload_size | |
id | 1086937 |
size | 25,277 |
Mock any function in Rust.
Make sure to only use this crate for testing purposes, as it will add a lot of overhead to your code.
On the function you want to mock, add the #[mock]
attribute.
#[cfg_attr(test, mockem::mock)]
fn foo(a: &str) -> String {
format!("{a}")
}
fn bar() -> String {
format!("Hello, {}!", foo("bar"))
}
#[test]
fn test_fn() {
use mockem::MockCall;
foo.mock_once(|a| format!("mocked {a}"));
assert_eq!(&bar(), "Hello, mocked bar!");
// function works normally after mock return value is returned
assert_eq!(&bar(), "Hello, bar!");
}
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!");
}
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 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!");
}