Macro faux::when [−][src]
when!() { /* proc-macro */ }
Expand description
Creates a When
instance to mock a specific method in a struct.
Callers may specify argument matchers to limit the arguments for
which the method is mocked. Matchers can only be specified if all
arguments implement Debug
. The debug message
is printed if any of the arguments fail to match.
The method to mock must be be in an impl
blocked tagged by
#[methods]
.
Examples
#[faux::create] pub struct Foo {} #[faux::methods] impl Foo { pub fn some_method(&self, a: u32, b: i8) -> i32 { /* implementation code */ } } fn main() { let mut mock = Foo::faux(); // specify all arguments faux::when!(mock.some_method(8, 9)).then_return(10); // actual method calls have to match expectations assert_eq!(mock.some_method(8, 9), 10); // mock.some_method(1, 1); // <~~ panics - arguments do not match // check only the second argument faux::when!(mock.some_method(_, 4)).then_return(20); // only the second argument is being matched against // so the first argument could be anything assert_eq!(mock.some_method(999, 4), 20); assert_eq!(mock.some_method(123, 4), 20); // mock.some_method(999, 3); // <~~ panics - second argument does not match // no argument matchers faux::when!(mock.some_method).then_return(3); // the arguments do not matter at all assert_eq!(mock.some_method(1337, 20), 3); assert_eq!(mock.some_method(4, 5), 3); assert_eq!(mock.some_method(7, 6), 3); }
An argument mismatch would look something like:
thread 'main' panicked at 'failed to call mock on 'Foo::some_method':
✗ Arguments did not match
Expected: [8, 9]
Actual: [1, 1]
Argument 0:
Expected: 8
Actual: 1
Argument 1:
Expected: 9
Actual: 1
Argument Matchers
Argument matchers are specified by passing them to when!
:
faux::when!(my_struct.my_method(/* matchers here */));
This rougly translates to:
faux::when!(my_struct.my_method).with_args((/* matchers here */));
Matcher syntax
To make argument matching easy to use, when!
provides some
syntactic sugar that converts given arguments to the appropiate
ArgMatcher
and passes them to with_args
. If this proves
difficult in your use case, you can use with_args
directly.
Each of the following specify an equivalent ArgMatcher
for a
single argument:
when! arg | ArgMatcher |
---|---|
{expr} | eq({expr}) |
_ | any() |
_ == {expr} | eq_against({expr}) |
_ = {matcher} | {matcher} |
Replace _
with *_
in the last two rows to match against
references. More specifically, this converts the matcher from
ArgMatcher<T>
into ArgMatcher<&T>
using into_ref_matcher
.
Examples
#[faux::create] pub struct MyStruct; #[faux::methods] impl MyStruct { pub fn my_method(&self, a: &i32, b: i32) -> i32 { panic!() } } let mut my_struct = MyStruct::faux(); // the eq matcher works even though the first argument is a reference // the `_` matcher will match any argument faux::when!(my_struct.my_method(3, _)).then_return(4); assert_eq!(my_struct.my_method(&3, 20), 4); // a type that implements `PartialEq<i32>` but is not an `i32` #[derive(Debug)] struct OtherNumber(i64); impl PartialEq<i32> for OtherNumber { fn eq(&self, rhs: &i32) -> bool { self.0 == *rhs as i64 } } // `_ == {expr}` to test equality of different types // `*_ == {expr}` to dereference an argument before matching faux::when!(my_struct.my_method( *_ == OtherNumber(5), _ == OtherNumber(20), )).then_return(8); assert_eq!(my_struct.my_method(&5, 20), 8); // `_ = {matcher}` will pass the matcher to `with_args` as written // `*_ = {matcher}` will match against a dereferenced argument faux::when!(my_struct.my_method( *_ = faux::matcher::eq_against(OtherNumber(4)), _ = faux::matcher::eq(9), )).then_return(20); assert_eq!(my_struct.my_method(&4, 9), 20); // pattern! and from_fn! are allowed just as any other matcher faux::when!(my_struct.my_method( *_ = faux::pattern!(10..=20), _ = faux::from_fn!(|arg: &i32| *arg > 50), )).then_return(80); assert_eq!(my_struct.my_method(&11, 60), 80);