mockall
mockall copied to clipboard
Support for return_const Option<&T> and Result<&T, E>
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.
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.
I concur - this is a very handy feature to have.
@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?
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.
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?
@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()
}
}
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 (=