Add `Expectation` method `return_const_once`
I think it would be a great addition to add a return_const_once method to Expectation. It would work like a combination of return_once and return_const. The main reason I want this is so you could return a const without the value having to implement Clone.
An example where this would be useful: returning Result<Something + Clone, Error> where Error doesn't implement Clone but the function is only called once. As it is right now, this situation requires using return_once and cloning the value before hand. Whereas with this addition, you could simply do: mock.return_const_once(Ok(something.clone)). Although, there might be a simpler way now that I'm not aware of.
I'm happy to create a PR if this is a welcome addition.
Why do you need to clone the value before hand? Can't you do return_once(move || Ok(something))?
For example, the following won't compile:
use mockall::automock;
use std::error::Error;
#[derive(Clone, Debug)]
struct MyStruct {
some_field: i32,
}
#[automock]
trait MyTrait {
fn foo(&self) -> Result<MyStruct, Box<dyn Error>>;
}
fn main() {
let my_struct = MyStruct { some_field: 0 };
let mut mock = MockMyTrait::new();
mock.expect_foo().return_once(move || Ok(my_struct.clone()));
dbg!(my_struct);
}
with the following error:
if you remove the move from the closure, you get the following error:

which I think makes sense. Even though we're just cloning my_struct which only requires a reference, the compiler can't guarantee that the closure won't run after my_struct is dropped which would mean that it couldn't clone it. So, you have to add move to take ownership. But, of course, if it takes ownership, you can't use it afterwards. So, the only option is to clone it before hand, and move the cloned version into the course:
// . . .
fn main() {
let my_struct = MyStruct { some_field: 0 };
let cloned_my_struct = my_struct.clone();
let mut mock = MockMyTrait::new();
mock.expect_foo().return_once(move || Ok(cloned_my_struct));
dbg!(my_struct);
}
With the addition that I'm suggesting, this could be written as:
// . . .
fn main() {
let my_struct = MyStruct { some_field: 0 };
let mut mock = MockMyTrait::new();
mock.expect_foo().return_const_once(Ok(my_struct.clone()));
dbg!(my_struct);
}
Yep, that's correct. Of course, in this example my_struct is Clone, which means you would be fine to use plain return_const. Right?
Yes, MyStruct implements Clone but Result<MyStruct, Box<dyn Error>> doesn't. So, return_const won't work because it requires that its argument implements Clone and we're passing it Result<MyStruct, Box<dyn Error>>. For example:
use mockall::automock;
use std::error::Error;
#[derive(Clone, Debug)]
struct MyStruct {
some_field: i32,
}
#[automock]
trait MyTrait {
fn foo(&self) -> Result<MyStruct, Box<dyn Error + Send + Sync>>;
}
fn main() {
let my_struct = MyStruct { some_field: 0 };
let mut mock = MockMyTrait::new();
mock.expect_foo()
.return_const(Ok(my_struct.clone()) as Result<MyStruct, Box<dyn Error + Send + Sync>>);
dbg!(my_struct);
}
throws the following compiler error:

And, following the compiler's help to borrow doesn't work either.
I'm surprised that I'm the first to run into this problem because returning Result<Something, SomeErrorType> is, of course, such a common pattern. And, error types typically don't Implement Clone.
Also thanks for the quick feedback!