-
Notifications
You must be signed in to change notification settings - Fork 62
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
How to mock multiple impls of generic struct instances? #271
Comments
I think your usage is basically correct, but there are a couple of small problems:
Those two problems might not be cause of your compile failure, but first things first. What happens when you make the struct match the mock? |
Thats right: first things first!
mock! {
pub Envelope<T: 'static> {}
impl From<A> for Envelope<A> {
pub fn from(value: A) -> MockEnvelopeA;
}
impl From<B> for Envelope<B> {
pub fn from(value: B) -> MockEnvelopeB;
}
}
impl Envelope<A> {
fn send(&'_ mut self, e: E, f: F) -> Result<D> {
/* */
}
}
impl Envelope<C> {
fn send(&'_ mut self, e: E) -> Result<D> {
/* */
}
} and therefor the mocks are now: mock! {
pub EnvelopeA {
pub fn send<'a>(&'a mut self, e: E, f: F) -> impl Future<Output = Result<D>>;
}
}
mock! {
pub EnvelopeB {
pub fn send<'a>(&'a mut self, e: E) -> impl Future<Output = Result<D>>;
}
} With these changes I get the following errors:
The reason for my problem are the different method signatures of |
No, syn is just fine. The main problem, as you observed, is that mockall generates some non-generic code for every mocked function. That means that multiple mock impls of the same function (even if they have different generic parameters) cause name conflicts. So you have multiple problems:
So here are some possibilities:
mock!{
pub InnerEnvelope {
fn from_a(a: A) -> Self;
fn from_b(b: B) -> Self;
fn send_a(&self, e: E, f: F) -> impl Future<Output = Result<D>>;
fn send_b(&self, e: E) -> impl Future<Output = Result<D>>;
}
}
struct MockEnvelope<T> {
inner: MockInnerEnvelope,
t: std::marker::PhantomData<T>
}
impl From<A> for MockEnvelope<A> {
pub fn from(a: A) -> MockEnvelope {
Self {
inner: MockInnerEnvelope::from_a(a),
t: PhantomData
}
}
}
impl From<B> for MockEnvelope<B> {
pub fn from(b: B) -> MockEnvelope {
Self {
inner: MockInnerEnvelope::from_b(b),
t: PhantomData
}
}
}
impl MockEnvelope<A> {
pub fn send(&mut self, e: E, f: F) -> impl Future<Output = Result<D>> {
self.inner.send_a(e, f)
}
}
impl MockEnvelope<B> {
pub fn send(&mut self, e: E) -> impl Future<Output = Result<D>> {
self.inner.send_b(e)
}
} |
I take option 4 and that compiles without errors. |
A specific impl is an implementation of a trait on a generic struct with specific generic parameters, like `impl Foo for Bar<i32> {}` Issue #271
A specific impl is an implementation of a trait on a generic struct with specific generic parameters, like `impl Foo for Bar<i32> {}` Issue #271
A specific impl is an implementation of a trait on a generic struct with specific generic parameters, like `impl Foo for Bar<i32> {}` Issue #271
@ChriFo I fixed the problem with implementing the same trait multiple times on a generic struct. You should be able to just use plain |
Well, that's because |
Thanks for try to solve my problems ;-) My application works with the current latest version. use futures::Future;
use mockall::*;
mock! {
pub Envelope<T: 'static> {
fn fake_send(&self) -> impl Future<Output = Result<HttpResponse>>;
}
impl<HarborHook> From<(HarborHook, Option<(String, usize)>)> for Envelope<HarborHook> {
pub fn from(value: (HarborHook, Option<(String, usize)>)) -> Envelope<HarborHook>;
}
impl<Value> From<Value> for Envelope<Value> {
pub fn from(value: Value) -> Envelope<Value>;
}
}
impl MockEnvelope<HarborHook> {
fn send(&self, info: String, client: &Client, hash: String, config: &Config) -> impl Future<Output = Result<HttpResponse>> {
self.fake_send()
}
}
impl MockEnvelope<Value> {
pub fn send(&self, info: String, client: &Client, db: &Pool, config: &Config) -> impl Future<Output = Result<HttpResponse>> {
self.fake_send()
}
} I get:
|
Yep, not surprising. Each of those from methods creates a from context. In your case, you could easily implement From manually. But it would be nice to fix this problem more generally. Do you have any thoughts on what syntax Mockall should use to handle cases like this? |
Maybe something like a macro, e.g., |
First of all: Thank you for a very useful library.
I have this (simplified) data structure:
And I use is it like that:
When trying to mock it like that:
The following error appears:
Thank you for any helpful information.
The text was updated successfully, but these errors were encountered: