Mry
A simple but powerful mocking library for structs, traits, and function.
Features
- A really simple and easy API
- No need of switching between mock objects and real objects.
- Supports mocking for structs, traits, and functions.
- Supports partial mocking.
Example
Mocking a struct
We need to add an attribute #[mry::mry]
in the front of struct definition and impl block to mock them.
// This
// And this
#[mry::mry]
adds a visible but ghostly field mry
to your struct, so your struct must be constructed by the following ways.
// An easy way
new!
// is equivalent to:
Cat ;
// If you derive or impl Default trait.
default;
// or
Cat ;
Now you can mock it by using following functions:
mock_*(...).returns(...)
: Makes a mock to return a constant value.mock_*(...).returns_with(|arg| ...)
: Makes a mock to return a value with a closure (This is allowed to return!Clone
unlikereturns
cannot).mock_*(...).assert_called(...)
: Asserts that a mock was called with correct arguments and times, and returns call logs.
Examples
cat.mock_meow.returns;
cat.mock_meow.returns;
cat.mock_meow.returns_with; // return a dynamic value
cat.mock_meow.assert_called; // Assert called exactly 1 time with 3
cat.mock_meow.assert_called; // Assert called with any value
cat.mock_meow.assert_called; // or within the range
Release build
When release build, the mry
field of your struct will be zero size, and mock_*
functions will be unavailable.
impl Trait for Struct
Also, mocking of impl trait is supported in the same API.
Partial mocks
You can do partial mocking with using calls_real_impl()
.
Mocking a trait
Just add #[mry::mry]
as before;
Now we can use MockCat
as a mock object.
// You can construct it by Default trait
let mut cat = default;
// API's are the same as the struct mocks.
cat.mock_meow.returns;
assert_eq!;
We can also mock a trait by manually creating a mock struct. If the trait has a generics or associated type, we need to use this way.
async_trait
Add #[mry::mry]
with the async_trait attribute underneath.
Mocking a function
Add #[mry::mry]
to the function definition.
We need to acquire a lock of the function by using #[mry::lock(hello)]
because mocking of static function uses global state.
// This is required!
Mocking a associated function (static function)
Include your associated function into the impl block with #[mry::mry]
.
We need to acquire a lock for the same reason in mocking function above.
// This is required!
Rust Analyzer
Currently comprehensive support of proc macros is not available in rust-analyzer, so above examples are not fully recognized by rust-analyzer and completions and type hints are inconvenient.
You can support them via GitHub Sponsors or Open Collective.
Also, we can contribute to it on GitHub.