Support default implementation
I would like to be able to use the default implementation of a method. In #94 you had a valid point that every method must be driven by expectations, however maybe a Expectation::default_fn can be introduced.
This is an example:
use mockall::automock;
#[automock]
trait Foo {
fn bar(&self) -> i32;
fn foo(&self) -> i32 {
self.bar() + 1
}
}
fn main() {
let mut mock = MockFoo::new();
mock.expect_bar().return_const(123);
mock.expect_foo().default_fn();
assert_eq!(mock.foo(), 124);
}
What do you think?
I think you can already achieve what you want by using mock! instead of #[automock]. Try this:
trait Foo {
fn bar(&self) -> i32;
fn foo(&self) -> i32 {
self.bar() + 1
}
}
mock!{
Foo {}
impl Foo for Foo {
fn bar(&self) -> i32;
}
}
Also, if I were to add a new feature for this, I wouldn't use the default_fn method as you suggest, because that wouldn't work well with mock!. Instead, I think it would be better to decorate the method with an attribute like #[nomock], similarly to the #[concretize] attribute described at https://github.com/asomers/mockall/discussions/409.
what about detecting if a trait method SomeTrait::some_method(x) has a body, and if it does, simply create a new method like SomeTrait::some_method__default(x) which contains the method body.
Then if the user wants, they can simply call the default impl in the expectation for the method
let mock = MockSomeTrait::new()
mock.expect_some_method().returning(MockSomeTrait::some_method__default)
That way we don't have to have multiple usages of mock!, or no_mock, mock_all can just stash the default under some well-known name.
I could see some issues around complicated lifetimes and other things Mockall currently deals with tho.
No, that wouldn't work. It might work for a few simple cases, but it would be too fragile, because:
- The method body may assume that
Self==MyStructinstead ofMockMyStruct - Mockall puts that kind of stuff in a submodule, which may break use paths used by the method body.