Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How would one mock the following trait using automock/mock!?? #638

Open
ealders opened this issue Feb 7, 2025 · 4 comments
Open

How would one mock the following trait using automock/mock!?? #638

ealders opened this issue Feb 7, 2025 · 4 comments
Labels
question Usage question

Comments

@ealders
Copy link

ealders commented Feb 7, 2025

pub trait DbSessionTrait {
      async fn query_as<T>(&self, query: &str, params: &[& (dyn ToSql + Sync)]) -> Result<Vec<T>, Error>;
      async fn query(&self, query: &str, params: &[& (dyn ToSql + Sync)]) -> Result<Vec<Row>, Error>;
      async fn validate_schema_exists(&self, schema: &str) -> Result<bool, Error>;
    }

Looking for the best way to mock out this trait for unit testing... it does not seem to work with the automock or mock!. Wanted to get some advice on a way to mock this out even if I needed to build it out manually.

@asomers asomers added the question Usage question label Feb 7, 2025
@asomers
Copy link
Owner

asomers commented Feb 7, 2025

What error do you get when using #[automock]? I suspect that you'll have to add a : 'static bound to T.

@ealders
Copy link
Author

ealders commented Feb 7, 2025

Here's a dump from the compiler with 'static in there

error[E0106]: missing lifetime specifier
   --> src/modules/db.rs:207:64
    |
207 |     async fn query_as<T:'static>(&self, query: &str, params: &[& (dyn ToSql + Sync)]) -> Result<Vec<T>, Error>;
    |                                                                ^ expected named lifetime parameter
    |
help: consider using the `'__mockall_params` lifetime
    |
207 |     async fn query_as<T:'static>(&self, query: &str, params: &[&'__mockall_params  (dyn ToSql + Sync)]) -> Result<Vec<T>, Error>;
    |                                                                 +++++++++++++++++

error[E0637]: `&` without an explicit lifetime name cannot be used here
   --> src/modules/db.rs:207:64
    |
207 |     async fn query_as<T:'static>(&self, query: &str, params: &[& (dyn ToSql + Sync)]) -> Result<Vec<T>, Error>;
    |                                                                ^ explicit lifetime name needed here
    |
help: consider introducing a higher-ranked lifetime here
    |
205 ~   for<'a> #[automock]
206 |   pub trait DbSessionTrait {
207 ~     async fn query_as<T:'static>(&self, query: &str, params: &[&'a  (dyn ToSql + Sync)]) -> Result<Vec<T>, Error>;
    |

error[E0261]: use of undeclared lifetime name `'__mockall_params`
   --> src/modules/db.rs:205:3
    |
205 |   #[automock]
    |   ^^^^^^^^^^^- lifetime `'__mockall_params` is missing in item created through this procedural macro
    |   |
    |   undeclared lifetime
206 |   pub trait DbSessionTrait {
207 |     async fn query_as<T:'static>(&self, query: &str, params: &[& (dyn ToSql + Sync)]) -> Result<Vec<T>, Error>;
    |                       - help: consider introducing lifetime `'__mockall_params` here: `'__mockall_params,`
    |
    = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0106]: missing lifetime specifier
   --> src/modules/db.rs:208:50
    |
208 |     async fn query(&self, query: &str, params: &[& (dyn ToSql + Sync)]) -> Result<Vec<Row>, Error>;
    |                                                  ^ expected named lifetime parameter
    |
help: consider using the `'__mockall_params` lifetime
    |
208 |     async fn query(&self, query: &str, params: &[&'__mockall_params  (dyn ToSql + Sync)]) -> Result<Vec<Row>, Error>;
    |                                                   +++++++++++++++++

error[E0637]: `&` without an explicit lifetime name cannot be used here
   --> src/modules/db.rs:208:50
    |
208 |     async fn query(&self, query: &str, params: &[& (dyn ToSql + Sync)]) -> Result<Vec<Row>, Error>;
    |                                                  ^ explicit lifetime name needed here
    |
help: consider introducing a higher-ranked lifetime here
    |
205 ~   for<'a> #[automock]
206 |   pub trait DbSessionTrait {
207 |     async fn query_as<T:'static>(&self, query: &str, params: &[& (dyn ToSql + Sync)]) -> Result<Vec<T>, Error>;
208 ~     async fn query(&self, query: &str, params: &[&'a  (dyn ToSql + Sync)]) -> Result<Vec<Row>, Error>;
    |

error: `impl` item signature doesn't match `trait` item signature
   --> src/modules/db.rs:207:5
    |
207 |     async fn query_as<T:'static>(&self, query: &str, params: &[& (dyn ToSql + Sync)]) -> Result<Vec<T>, Error>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
    |     |
    |     found `fn(&'1 MockDbSessionTrait, &'2 str, &'3 [&(dyn tokio_postgres::types::ToSql + Sync + '__mockall_params)]) -> impl futures_core::Future<Output = Result<Vec<T>, tokio_postgres::Error>>`
    |     expected `fn(&'1 MockDbSessionTrait, &'2 str, &'3 [&dyn tokio_postgres::types::ToSql + Sync]) -> _`
    |
    = note: expected signature `fn(&'1 MockDbSessionTrait, &'2 str, &'3 [&dyn tokio_postgres::types::ToSql + Sync]) -> _`
               found signature `fn(&'1 MockDbSessionTrait, &'2 str, &'3 [&(dyn tokio_postgres::types::ToSql + Sync + '__mockall_params)]) -> impl futures_core::Future<Output = Result<Vec<T>, tokio_postgres::Error>>`
help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
   --> src/modules/db.rs:207:101
    |
207 |     async fn query_as<T:'static>(&self, query: &str, params: &[& (dyn ToSql + Sync)]) -> Result<Vec<T>, Error>;
    |                                                                                                     ^ consider borrowing this type parameter in the trait

error: `impl` item signature doesn't match `trait` item signature
   --> src/modules/db.rs:208:5
    |
208 |     async fn query(&self, query: &str, params: &[& (dyn ToSql + Sync)]) -> Result<Vec<Row>, Error>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
    |     |
    |     found `fn(&'1 MockDbSessionTrait, &'2 str, &'3 [&(dyn tokio_postgres::types::ToSql + Sync + '__mockall_params)]) -> impl futures_core::Future<Output = Result<Vec<tokio_postgres::Row>, tokio_postgres::Error>>`
    |     expected `fn(&'1 MockDbSessionTrait, &'2 str, &'3 [&dyn tokio_postgres::types::ToSql + Sync]) -> _`
    |
    = note: expected signature `fn(&'1 MockDbSessionTrait, &'2 str, &'3 [&dyn tokio_postgres::types::ToSql + Sync]) -> _`
               found signature `fn(&'1 MockDbSessionTrait, &'2 str, &'3 [&(dyn tokio_postgres::types::ToSql + Sync + '__mockall_params)]) -> impl futures_core::Future<Output = Result<Vec<tokio_postgres::Row>, tokio_postgres::Error>>`
    = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
    = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output

error[E0277]: the trait bound `for<'__mockall_params> MockallMatcher1: Predicate<[&'__mockall_params (dyn tokio_postgres::types::ToSql + Sync + '__mockall_params)]>` is not satisfied
   --> src/modules/db.rs:205:3
    |
205 |   #[automock]
    |   ^^^^^^^^^^^ the trait `for<'__mockall_params> Predicate<[&'__mockall_params (dyn tokio_postgres::types::ToSql + Sync + '__mockall_params)]>` is not implemented for `MockallMatcher1`
    |
    = note: required for the cast from `Box<MockallMatcher1>` to `Box<dyn Predicate<[&dyn ToSql + Sync]> + Send>`
    = note: the full name for the type has been written to '/Users/ealders/code/strenuus/provider-nexus-api/target/debug/deps/provider_nexus-e0e2438c84565d24.long-type-6529247397761219127.txt'
    = note: consider using `--verbose` to print the full type name to the console
    = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `for<'__mockall_params> MockallMatcher1: Predicate<[&'__mockall_params (dyn tokio_postgres::types::ToSql + Sync + '__mockall_params)]>` is not satisfied
   --> src/modules/db.rs:205:3
    |
205 |   #[automock]
    |   ^^^^^^^^^^^ the trait `for<'__mockall_params> Predicate<[&'__mockall_params (dyn tokio_postgres::types::ToSql + Sync + '__mockall_params)]>` is not implemented for `MockallMatcher1`
    |
    = note: required for the cast from `Box<MockallMatcher1>` to `Box<dyn Predicate<[&dyn ToSql + Sync]> + Send>`
    = note: the full name for the type has been written to '/Users/ealders/code/strenuus/provider-nexus-api/target/debug/deps/provider_nexus-e0e2438c84565d24.long-type-192473539372891870.txt'
    = note: consider using `--verbose` to print the full type name to the console
    = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

@asomers
Copy link
Owner

asomers commented Feb 7, 2025

Those errors are saying that you need to add a lifetime parameter to the references in your function arguments. The easiest one to add is 'static. Can you do that?

@ealders
Copy link
Author

ealders commented Feb 7, 2025

Yeah... it looks like it is conflicting with the lifetime added by automock.

error[E0261]: use of undeclared lifetime name `'__mockall_params`
   --> src/modules/db.rs:205:3
    |
205 |   #[automock]
    |   ^^^^^^^^^^^- lifetime `'__mockall_params` is missing in item created through this procedural macro
    |   |
    |   undeclared lifetime
206 |   pub trait DbSessionTrait {
207 |     async fn query_as<T:'static>(&self, query: &str, params: &[&'static (dyn ToSql + Sync)]) -> Result<Vec<T>, Error>;
    |                       - help: consider introducing lifetime `'__mockall_params` here: `'__mockall_params,`
    |
    = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: method not compatible with trait
   --> src/modules/db.rs:207:5
    |
207 |     async fn query_as<T:'static>(&self, query: &str, params: &[&'static (dyn ToSql + Sync)]) -> Result<Vec<T>, Error>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
    = note: expected signature `fn(&MockDbSessionTrait, &_, &[&'static (dyn tokio_postgres::types::ToSql + Sync + 'static)]) -> _`
               found signature `fn(&MockDbSessionTrait, &_, &[&'static (dyn tokio_postgres::types::ToSql + Sync + '__mockall_params)]) -> _`
note: the lifetime `'__mockall_params` as defined here...
   --> src/modules/db.rs:205:3
    |
205 |   #[automock]
    |   ^^^^^^^^^^^
    = note: ...does not necessarily outlive the static lifetime
    = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: method not compatible with trait
   --> src/modules/db.rs:208:5
    |
208 |     async fn query(&self, query: &str, params: &[&'static (dyn ToSql + Sync)]) -> Result<Vec<Row>, Error>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
    = note: expected signature `fn(&MockDbSessionTrait, &_, &[&'static (dyn tokio_postgres::types::ToSql + Sync + 'static)]) -> _`
               found signature `fn(&MockDbSessionTrait, &_, &[&'static (dyn tokio_postgres::types::ToSql + Sync + '__mockall_params)]) -> _`
note: the lifetime `'__mockall_params` as defined here...
   --> src/modules/db.rs:205:3
    |
205 |   #[automock]
    |   ^^^^^^^^^^^
    = note: ...does not necessarily outlive the static lifetime
    = note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Usage question
Projects
None yet
Development

No branches or pull requests

2 participants