-
Notifications
You must be signed in to change notification settings - Fork 66
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
Support returning future #400
Comments
If you defined the method as "async fn", then the generated code expects your expectation function to provide an immediate value, and it will add the pub fn read(&self) -> impl Future<Output = io::Result<()>> {...} |
Ok I am confused. Am I expected to change the tested code return type just to be able to have mocked delays? Isn't the whole purpose of async keyword to not do this? |
Could we maybe have two separate methods?
This would make it more clear what is happening and how to gain back control. It would also not require hopefully adapting fundamental code for tests. |
Yes, you will need to change the function signature to accomplish what you want. No, we can't just add a different returning method, because it's an issue in the code generation that affects more than just that method. No, you aren't the only person who's ever been confused by this. But the existing behavior is actually convenient for most users, and making the behavior selectable would probably require adding some kind of attribute to the function to control Mockall's code generation. That, too, would be a form of changing the function signature. |
Maybe having another mock macro |
Or maybe having a second argument on |
In case it helps anyone, I've also run into this issue an was able to work around it by wrapping a call to the |
@savudani8 Your solution uses the proposed alternative of using |
@asomers I've attempted to use this solution but since what I am So basically looking at @savudani8`s solution I arrived at: // From simply having:
#[async_trait]
pub trait Trait {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
}
// To having:
pub trait Trait {
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> BoxFuture<'a, Result<usize>>;
} In the process I have:
Now the above compiles and runs, but there is an issue with 21 | fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> BoxFuture<'a, Result<usize>>;
| ------------ --- ...is used here...
| |
| this data with lifetime `'a`...
|
note: ...and is required to live as long as `'static` here
--> src/utils/internal_serial_port.rs:19:18
|
19 | #[cfg_attr(test, automock)]
| ^^^^^^^^
= note: this error originates in the attribute macro `automock` (in Nightly builds, run with -Z macro-backtrace for more info) So in a sense I am forced to use At this stage I would argue that |
So I got until this point. mock! {
//...
fn read<'a, 'b, 'c>(&'a mut self, buf: &'b mut [u8])
-> Pin<Box<dyn Future<Output = Result<usize>> + Send + 'c>>
where 'a: 'c, 'b: 'c;
//...
}
// ...
port.expect_read()
.times(1)
.returning(|mut buf: &mut[u8]| Box::pin(async {
buf.write(&bytes)
})); The issue is that this doesn't work:
Is this really impossible? If I understand correctly 'c needs to be static, 'c and 'b can be 'static, but 'a cannot be since that is the instance of the mock trait, and there is a relationship required that 'a lives as much as 'c |
Have you tried #[cfg_attr(test, automock)]
#[async_trait]
pub trait Trait {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
} I'm also mocking async calls and after fiddling with the order of derives, the specific way automock is imported, etc I got a similar structure to work for me. #[cfg_attr(test, automock)]
#[async_trait]
pub trait NostrPowProviderTrait {
async fn automine(&self, target_difficulty: u8, message: String) -> anyhow::Result<MinedNote>;
} and in tests #[tokio::test]
async fn automine_when_criteria_fit() {
// ...
p.expect_automine().times(1).returning(|_diff, _msg| create_random_mined_note());
} |
@ok300 I think you are missing the point. Automock will mock the method in a way that you cannot control a delay on the returned promise. It has 0 delay. I am trying to return in the mocked method call an actual future so I can delay it. |
@archfz "supporting #[async_trait] with #[automock] is incomplete" is truly only in the sense that |
Closing this because the original question has been answered. BTW, see #189 for the enhancement request that would cleanly solve the problem. |
I am mocking a method that is async. The mocked method is called in context of a timeout (from tokio). I would like to add a delay to the mocked return value. Something like this:
I get the following error:
Maybe there is another way of doing this, but I haven't found anything useful. Especially in the mockall documentation. The upper described way was my natural first instinct to implement this.
The text was updated successfully, but these errors were encountered: