# async-mock [github](https://github.com/SignalWhisperer/async-mock-rs) [crates.io](https://crates.io/crates/async-mock) [docs.rs](https://docs.rs/async-mock) Async trait mocking library for Rust. Also supports mocking non-async traits. ### Usage `async-mock` is normally used for testing only. To do so, add it to `Cargo.toml` as such: ```cargo [dev-dependencies] async-mock = "0.1.3" ``` Then you can use it as such: ```rust #[cfg(test)] use async_mock::async_mock; use async_trait::async_trait; #[cfg_attr(test, async_mock)] #[async_trait] trait MyTrait { async fn foo(&self, x: i32) -> i32; } #[derive(Default)] struct MyStruct; impl MyStruct { async fn bar(&self, my_trait: &impl MyTrait, x: i32) -> i32 { my_trait.foo(x * 2).await } } #[cfg(test)] mod tests { use super::*; #[tokio::test] async fn some_test() { let mut mock = MockMyTrait::default(); mock.expect_foo() .times(1) .returning(|x| x + 1); let system_under_test = MyStruct::default(); assert_eq!(7, system_under_test.bar(&mock, 3).await); } } ``` The traits will have a mock structure created named by prefixing `Mock` to the trait name. This structure implements the trait and all of its functions. To setup the mocking, call the `expect_*` functions, where `*` is the name of the function you want to mock. This returns a mutable reference to an expectation object on which you can set the mocking expectations. To set the number of expected calls, you can use `once()`, `never()`, or `times(u32)`. To set the mocked return value, call `returning` with a closure that takes the same arguments as your trait function. If your trait function has an argument that contains a `&impl`, you must call `returning_dyn` instead and enclose your closure in a `Box`. ### Limitations As of v0.1.3, `async-mock` does not support generics and has a hard-coded dependency on [async-trait](https://crates.io/crates/async-trait), which you should be using already anyway. There may be many edge cases not covered, it does not support input filtering, and it does not support passing through a sequence of functions across multiple invocations. There are many more limitations since this crate is fairly young. Pull requests are welcome! Non exhaustive list of limitations: - When mocking an async trait that has an `&impl` argument, you must call `returning_dyn` instead of `returning` and put the closure into a `Box`. - Calling async functions from the mocking closures passed to `returning()` and `returning_dyn()` is not supported. - Generics are not supported. ### Acknowledgements `async-mock` takes great inspiration from [Mockall](https://crates.io/crates/mockall) and actually aims to complete it by covering the use case of async traits, which Mockall currently does not support very well. `async-mock` aims to be a nearly drop-in replacement for Mockall when it comes to async traits only, but not a replacement when it comes to everything else.