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

Mocking a function taking an FnMut closure incompatible with concretize #577

Open
vlovich opened this issue May 12, 2024 · 1 comment
Open
Labels
bug Something isn't working

Comments

@vlovich
Copy link

vlovich commented May 12, 2024

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);
}
@asomers
Copy link
Owner

asomers commented May 12, 2024

I think you've found a bug. I'll look into it.

@asomers asomers added the bug Something isn't working label May 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants