It is now possible to mock generic trait with type parameter bounds. Trait
bounds and 'static
lifetime are supported:
#[mocked]
trait <T: 'static + std::fmt::Display> {}
There was error causing simple matchers (created with eq
, lt
, etc.) to
always be displayed as 'lt'.
Previously, you had to use exactly same type for argument matcher, e.g. for
method accepting string you had to provide String
instance:
trait A { fn foo(&self, s: String) }
handle.foo(String::from("bar"));
Now you can use any type comparable to one of method parameter, e.g. &str
for String
parameter:
handle.foo("bar");
Now you can mock methods with arbitrary self
type, for example
self: Box<Self>
or self: Rc<Self>
.
Scenario::create_mock*
methods now return tuple (mock, handle)
instead of
just mock
. Why? For two reasons:
- Mocks can now be freely moved, not just passed by reference, because you always have "remote control" in your hand;
- Making mock and handle separate objects allows to git rid of
_call
suffix on stub methods, they can now be named after original ones.
So, summarizing, before:
let scenario = Scenario::new();
let mock = scenario.create_mock_for::<dyn A>();
scenario.expect(mock.foo_call().and_return(()));
mock.foo();
After:
let scenario = Scenario::new();
let (mock, handle) = scenario.create_mock_for::<dyn A>();
scenario.expect(handle.foo().and_return(()));
// ^ `handle.foo`, not `mock.foo_call`
mock.foo();
Use derive
attribute option to derive Clone
implementation instead of
mock_clone
.
Before:
#[mocked(AMock)] trait A { .. }
mock_clone!(AMock);
#[mocked(BMock)] trait B { .. }
mock_clone!(BMock, share_expectations);
After:
#[mocked(AMock, derive(Clone))] trait A { .. }
#[mocked(BMock, derive(Clone(share_expectations)))] trait B { .. }
There is 'debug' feature which causes macros to print generated code to stderr. Now this code may be formatted using 'rustfmt', just turn on 'debug-rustfmt' feature.
Additionally, debug print is now turned on on per-attribute basis using 'debug' attribute option:
#[mocked(debug)] trait A { .. }
Unfortunately, output from all mock!
invocations is still printed when 'debug'
feature is on, this will be fixed later.
Not it is possible to mock traits with both type parameters and associated types.
Deriving Clone
now works for generic traits.
Traits from another modules or crates may be mocked with mocked
attribute,
just copy trait definition and use 'extern' option:
#[mocked(AMock, extern, module="::another::module")]
trait A { .. }
Mock name must be provided, because it is not possible to use create_mock_for
,
only create_mock
. Module path is mandatory, and it must be absolute (starting
either with '::' or 'crate::').
There is now once()
shortcut for times(1)
:
scenario.expect(handle.foo().and_return_clone(1).once());
by_ref
matcher allows matching value behind the reference:
handle.method_with_ref_arg(by_ref(lt(3))).and_return(());
Errors reporting is improved using proc_macro_diagnostic
feature available on
nightly. Errors can now be attached to positions in source code, so it's
easier to find the cause. Additionally examples are added to some error messages. So
it looks like this:
error: Unfortunately, macro can't get full path to referenced parent trait, so it must be be given using 'refs' parameter:
#[mocked]
trait A {}
#[mocked(refs = "A => ::full::path::to::A")]
trait B : A {}
--> $DIR/parent_ref.rs:6:11
|
6 | trait B : A {}
| ^