Closed sadokmtir closed 1 year ago
Your problem is worse than simply wanting to opt-out of mocking one particular method. Your real problem is that you're trying to mix real objects and mock objects in the same code. Your definition for fake
tries to create a real APIAccess
object, but you're calling it in a a context that expects MockAPIAccess
. You need to decide which object type you want, and stick with it.
That is just a static method that the mockall mocks by default and there is no way to workaround it besides importing the APIAccess
and MockAPIAccess
separately. If there is a way how to skip mocking a specific function that would solve the problem here. Also not that this is just the test function not the application code. The uses case being tested requires both objects and Mocks. For example: getting the mock object from the request context and having a service that loads the objects from external resource. In this case you need both, you need a mock object for the object deducted from the context and you need an object double to return them when you mock the service call. I see this as very common uses case. So, I really don't get why I need to stick with one of them.
If there is a way how to skip mocking a specific function that would solve the problem here
Yes there is such a way, but no it won't solve your problem.
The uses case being tested requires both objects and Mocks
You cannot mix real objects and mock objects in the same code. The real object is replaced at compile-time with a different object. The mock object likely has a different size and definitely has different methods. It is not a trait object, that can be swapped in at runtime. In this case, you've clearly defined MockApiPermissionService::list
as returning a vec of MockApiAccess
. So there's no possible way for it to return a real ApiAccess
.
It's normal that you want to have tests for real ApiAccess
objects, and also tests that make use of MockApiAccess
. But you've got to separate them at compile-time. Any struct defined in terms of one cannot work with the other.
Yes there is such a way, but no it won't solve your problem.
What is the way if we have a struct with some function that I do not want to mock ? Apart from this example, I always have the need in other examples, where the struct has several methods that I don't want to mock all of them. The workaround you presented here https://github.com/asomers/mockall/issues/242#issuecomment-757541247 does not solve the issue as there is no Trait involved.
You can do it like this:
struct Foo {}
#[automock]
impl Foo {
fn foo(&self){...}
}
impl Foo {
fn bar(&self){...}
}
In this way, the foo
method will be mocked, but bar
will not.
Thanks but in my case I cannot use the #[automock]
instead I am using the mock!()
macro. How could I do it in that case ?
That's even easier. Just don't put bar
in the mock!
invocation.
Closing on the assumption that the OP's concerns have been adequately answered.
It would be nice to skip the generation for some methods marked with a Macro attribute for example.
In my uses case, I have a struct that it is auto-mocked using mockall and I use some fake method in its struct to genrate a test double for my unit tests. Here is an example:
I would like to be able in my test to have expectation for the method
is_admin
and also be able to use some fake data for the Struct.On the line where I call
APIAccess::fake()
, my test panics with the message: No matching expectation found. Because I am getting an automatic mock implementation for it.PS: I already checked this issue https://github.com/asomers/mockall/issues/242 and I don't see how the proposed solution could solve my problem unfortunately.