Closed Tockra closed 4 months ago
automock does work with async_trait. For example, see https://github.com/asomers/mockall/blob/master/mockall/tests/automock_async_trait.rs . The main thing to be aware of is that the automock attribute must precede the async_trait attribute.
Okay, my program does not compile if I do it. Maybe somebody could assist to fix the example above.
Maybe you could post the error message?
Of course:
error: future cannot be sent between threads safely
--> src/db/mod.rs:30:1
|
30 | #[automock]
| ^^^^^^^^^^^ future created by async block is not `Send`
|
note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send`
--> src/db/mod.rs:45:27
|
45 | async fn connect(&mut self, config: &Config) -> Result<(), mongodb::error::Error>;
| ^^^^ has type `&mut MockDatabaseService<T>` which is not `Send`, because `MockDatabaseService<T>` is not `Send`
= note: required for the cast from `Pin<Box<{async block@src/db/mod.rs:30:1: 30:12}>>` to `Pin<Box<(dyn futures::Future<Output = Result<(), mongodb::error::Error>> + std::marker::Send + 'async_trait)>>`
= note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider further restricting this bound
|
32 | pub trait DatabaseService<T: model::Element + std::marker::Send>: Debug + Sync + Send {
| +++++++++++++++++++
Did you try following the compiler's advice?
After fullfilling the suggestions step for step I arrived at:
#[cfg(test)]
use mockall::{automock, mock, predicate::*};
#[cfg_attr(test, automock)]
#[async_trait]
pub trait DatabaseService<T: model::Element + std::marker::Send + std::marker::Sync>:
Debug + Sync + Send
// ...
With error message:
error[E0277]: `(dyn std::any::Any + 'static)` cannot be sent between threads safely
--> src/db/mod.rs:30:11
|
30 | pub trait DatabaseService<T: model::Element + std::marker::Send + std::marker::Sync>:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn std::any::Any + 'static)` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `(dyn std::any::Any + 'static)`, which is required by `MockDatabaseService<T>: std::marker::Send`
= note: required for `Unique<(dyn std::any::Any + 'static)>` to implement `std::marker::Send`
note: required because it appears within the type `Box<(dyn std::any::Any + 'static)>`
--> /Users/titan/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/boxed.rs:197:12
|
197 | pub struct Box<
| ^^^
note: required because it appears within the type `__as_any::Rfunc<T>`
--> src/db/mod.rs:28:18
|
28 | #[cfg_attr(test, automock)]
| ^^^^^^^^
note: required because it appears within the type `__as_any::Expectation<T>`
--> src/db/mod.rs:28:18
|
28 | #[cfg_attr(test, automock)]
| ^^^^^^^^
= note: required for `Unique<__as_any::Expectation<T>>` to implement `std::marker::Send`
note: required because it appears within the type `alloc::raw_vec::RawVec<__as_any::Expectation<T>>`
--> /Users/titan/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:69:19
|
69 | pub(crate) struct RawVec<T, A: Allocator = Global> {
| ^^^^^^
note: required because it appears within the type `Vec<__as_any::Expectation<T>>`
--> /Users/titan/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:398:12
|
398 | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
| ^^^
note: required because it appears within the type `__as_any::Expectations<T>`
--> src/db/mod.rs:28:18
|
28 | #[cfg_attr(test, automock)]
| ^^^^^^^^
note: required because it appears within the type `MockDatabaseService_DatabaseService_13065831140148901594<T>`
--> src/db/mod.rs:30:11
|
30 | pub trait DatabaseService<T: model::Element + std::marker::Send + std::marker::Sync>:
| ^^^^^^^^^^^^^^^
note: required because it appears within the type `MockDatabaseService<T>`
--> src/db/mod.rs:30:11
|
30 | pub trait DatabaseService<T: model::Element + std::marker::Send + std::marker::Sync>:
| ^^^^^^^^^^^^^^^
note: required by a bound in `DatabaseService`
--> src/db/mod.rs:31:20
|
30 | pub trait DatabaseService<T: model::Element + std::marker::Send + std::marker::Sync>:
| --------------- required by a bound in this trait
31 | Debug + Sync + Send
| ^^^^ required by this bound in `DatabaseService`
= note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)
That message is telling you that the as_any
method's return value is not Send
. Try adding a + Send
trait bound to it.
Hello,
I still have to use the
async_trait
crate because I have a trait where I need to create trait objects. This seems to be impossible if the trait contains async methods. So I have this:Now I'm having problems using
mockall
with this.Automock
does not work, and I have tried multiple variants ofmock!
.Maybe somebody can give me a hint on how I can mock a test for the following function:
I just want to test a few things:
get_positions
function calls theget_documents
function of the passedDatabaseService
.get_positions
function returns the result ofdb.get_documents()
.Does anybody have a hint for me on how to achieve this?
Thanks!