Closed asomers closed 2 years ago
This seems great and I'd love to use it, but unless I'm doing something very wrong, it doesn't seem to work if mockall
is a dev-dependency.
Specifically, the problem is that #[mockall::concretize]
only seems to take effect when used directly, and #[cfg_attr(test, mockall::concretize)]
has no effect. This means that mockall must be present in non-test builds, which is far from ideal.
I'm guessing this is something to do with the following line in the docs, suggesting that the attribute is more of a textual marker than taking effect directly:
NB: This attribute must be imported with its canonical name. It won't work otherwise!
Is this fixable?
Hm, you must be doing something wrong, because I use concretize
with mockall
as a dev-dependency. The warning you mention isn't related. It just means, don't do something like import mockall::concretize as something_else
.
Let me provide an example, and hopefully you can tell me what I'm doing wrong.
The following is based on the example in the docstring:
use std::path::Path;
#[cfg(test)]
use mockall::{automock, concretize};
#[cfg_attr(test, automock)]
trait Foo {
#[concretize]
fn foo<P: AsRef<Path>>(&self, p: P);
}
fn main() {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn some_test() {
let mut mock = MockFoo::new();
mock.expect_foo()
.withf(|p| p.as_ref() == Path::new("/tmp"))
.return_const(());
mock.foo(Path::new("/tmp"));
}
}
This works fine in test mode, but cargo check
errors out because #[concretize]
isn't defined. If I simply change #[concretize]
to #[cfg_attr(test, concretize)]
, then it compiles fine in normal mode, but the following errors spew out in test mode:
error[E0658]: attributes on expressions are experimental [0/464] --> src/main.rs:8:22
|
8 | #[cfg_attr(test, concretize)]
| ^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
error: expected non-macro attribute, found attribute macro `concretize`
--> src/main.rs:8:22
|
8 | #[cfg_attr(test, concretize)]
| ^^^^^^^^^^ not a non-macro attribute
error[E0658]: custom attributes cannot be applied to expressions
--> src/main.rs:8:22
|
8 | #[cfg_attr(test, concretize)]
| ^^^^^^^^^^
|
= note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information
error[E0310]: the parameter type `P` may not live long enough
--> src/main.rs:6:18
|
6 | #[cfg_attr(test, automock)]
| ^^^^^^^^ ...so that the type `Expectations<P>` will meet its required lifetime bounds...
|
note: ...that is required by this bound
--> /home/cjriches/.cargo/git/checkouts/mockall-17cf93ce910ebbb5/b51cb30/mockall/src/lib.rs:1418:29
|
1418 | pub trait AnyExpectations : Any + Send + Sync {}
| ^^^
= note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider adding an explicit lifetime bound...
|
9 | fn foo<P: AsRef<Path>> + 'static(&self, p: P);
| +++++++++
error[E0310]: the parameter type `P` may not live long enough
--> src/main.rs:6:18
|
6 | #[cfg_attr(test, automock)]
| ^^^^^^^^ ...so that the type `P` will meet its required lifetime bounds...
|
note: ...that is required by this bound
--> /home/cjriches/.cargo/git/checkouts/mockall-17cf93ce910ebbb5/b51cb30/mockall/src/lib.rs:1418:29
|
1418 | pub trait AnyExpectations : Any + Send + Sync {}
| ^^^
= note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider adding an explicit lifetime bound...
|
9 | fn foo<P: AsRef<Path>> + 'static(&self, p: P);
| +++++++++
The last two errors seem to just be the effects of concretize
not happening, but the first few are more worrying.
How do I get concretize
to compile under both normal and test mode?
Yep, it's a bug. I never noticed because I've only used concretize with mock!
, not #[automock]
. Moving discussion to https://github.com/asomers/mockall/issues/427 .
Add a #[mockall::concretize] attribute. When set on a function or method, its generic expectations will be turned into trait objects.
But it only works for function arguments that are pure generic types or a few basic combinations:
Issue #217