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

Support for return_const Option<&T> and Result<&T, E> #387

Open
neilisaac opened this issue Jun 13, 2022 · 7 comments
Open

Support for return_const Option<&T> and Result<&T, E> #387

neilisaac opened this issue Jun 13, 2022 · 7 comments

Comments

@neilisaac
Copy link

Mocking a trait method fn foo(&self) -> Option<&T> is difficult because return_const wants Option<&T>, so the mock doesn't own the value. It would be more useful if return_const would accept Option<T> (similar to a mocked method returning &T) instead so that the expectation can own the T and return a reference to it. I had to use lazy_static to work around this.

@asomers
Copy link
Owner

asomers commented Jun 13, 2022

That would be handy, but there are infinitely many possible structs that might be parameterized on &T. Can you think of a more general way to design this feature, preferably one that is possible to implement? I couldn't.

@krojew
Copy link

krojew commented Jan 17, 2023

I concur - this is a very handy feature to have.

@neilisaac
Copy link
Author

@asomers in general supporting something like fn return_ref_from<V: AsRef<T>>(value: V) might allow for a more general solution by internally storing value as a Box<dyn AsRef<T>>. Unfortunately Option implements its own as_ref method rather than implementing AsRef, so I don't think there's an existing trait that can be leveraged directly for Option. Mockall could expose its own trait similar to AsRef, which is implemented for both Option and AsRef. Would that work?

@asomers
Copy link
Owner

asomers commented Feb 9, 2023

That would only work if you want the mock method to return &T, right? That's already possible using return_ref. So I don't see what this proposal would add.

@gollth
Copy link

gollth commented Feb 19, 2024

Is there now a way to mock a method returning Option<&T> without a 'static lifetime? Could you give an example @asomers how one would approach this?

@asomers
Copy link
Owner

asomers commented Feb 19, 2024

@gollth there isn't a way to do it automatically. You'll have to do it at least partly by hand. Perhaps something like this:

struct MyStruct<T> {...}
impl<T> MyStruct<T> {
    fn foo(&self) -> Option<&T>;
}
mock!{
    MyStruct<T: 'static> {
        fn _foo(&self) -> Option<T>
    }
}
impl<T: 'static> MockMyStruct<T> {
    fn foo(&self) -> Option<&T> {
        self._foo().as_ref()
    }
}

@gollth
Copy link

gollth commented Feb 19, 2024

Thanks for the quick answer @asomers. This would probably work. A colleague of mine suggested another approach, by leaking a Box into a static reference:

struct X;  // dummy payload

#[mockall::automock]
trait Foo {
    fn foo(&self) -> Option<&X>;
}

#[test]
fn test() {
    let mut mock = MockFoo();
    let x = Box::leak(Box::new(Some(X)));
    mock.expect_foo().return_const(x.as_ref());
    // ...
}

This works for my use case (non-generic signature). Don't know if this helps for the original question, just thought I post here for reference (=

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants