Description
Tried on Stackoverflow but I think this won't get the right eyes there. I have a trait I'm trying to mock that looks like below. It has a for_each
method that takes an FnMut and invokes it on all items of interest. UnderTest is the thing I'm trying to test where I give it a mocked Foo instance and it calls for_each and does something with each element. The problem is that when I use concretize
, the returning
expectation receives a &dyn FnMut
instead of &mut dyn FnMut
meaning I can't invoke the callback to invoke the closure do_something provides. If I get rid of #[concretize]
& make F: 'static
for for_each
, then I get an invokable function, but then do_something
won't compile because &mut sum
doesn't have static lifetime (i.e. the static
lifetime is purely for mocking & adds requirements I don't need when I don't mock).
Is there a better way?
#[cfg_attr(test, automock)]
trait Foo {
#[cfg_attr(test, concretize)]
fn for_each<F>(&self, processor: F)
where
Self: Sized,
F: FnMut(&u32);
}
#[derive(Default)]
struct UnderTest;
impl UnderTest {
fn do_something<F: Foo>(&self, foo: &F) {
let mut sum = 0;
let sum_mut = &mut sum;
foo.for_each(|x| {
*sum_mut += *x;
})
eprintln!("Sum of all numbers is {sum}");
}
}
#[cfg(test)]
#[test]
fn do_something() {
let mut foo = MockFoo::new();
foo.expect_for_each().times(1).returning(|cb| {
cb(&0);
cb(&1);
});
let t = UnderTest::default();
t.do_something(&foo);
}