Comments (4)
run
is definitely getting called. That's why pre_execute
is being called, after all. And pre_execute panics because you never set any expectations for it. Unless you're using the nightly
flag, you need to add some variation of .returning
to every expectation . I'm actually surprised that this compiles. There shouldn't be any method bodies inside of mock!
, because they don't do anything there.
from mockall.
@asomers thanks for your response! I have updated my test code and I'm still seeing the failure.
tests.rs:
use anyhow::Result;
use mockall::mock;
use super::Command;
mock! {
PreExecFailure{}
impl Command for PreExecFailure {
// mock these three methods only, not run
async fn pre_execute(&self) -> Result<()>;
async fn execute(&self) -> Result<()>;
async fn post_execute(&self, result: Result<()>) -> Result<()>;
}
}
#[tokio::test]
async fn test_pre_exec_failure() {
let mut mock = MockPreExecFailure::new();
mock.expect_pre_execute().returning(|| Err(anyhow::anyhow!("Error")));
mock.expect_execute().returning(|| Ok(()));
mock.expect_post_execute().returning(|_r| Ok(()));
assert!(mock.run().await.is_err(), "Command::run should have returned an error on failed pre_execute");
// execute should never have been called
mock.expect_execute().never();
// pre-execute should have been called once
mock.expect_pre_execute().times(1);
}
The other source file has not changed.
Here is the failed output:
MockPreExecFailure::pre_execute: Expectation(<anything>) called 0 time(s) which is fewer than expected 1
I can observe that execute
was never called, but pre_execute
was never called according to the mock. With debug points, I can see that pre_execute
was indeed called, but I don't know why it doesn't register as having been called.
from mockall.
You can't set expectations after calling the code under test. Mockall doesn't work that way. You have to set them before.
from mockall.
I was able to resolve the issue, full code:
tests.rs:
use anyhow::{anyhow, Result};
use mockall::mock;
use super::Command;
mock! {
Exec{}
impl Command for Exec {
// mock these three methods only, not run
async fn pre_execute(&self) -> Result<()>;
async fn execute(&self) -> Result<()>;
async fn post_execute(&self, result: Result<()>) -> Result<()>;
}
}
/// A pre-exec failure should mean that exec is never called, nor post-exec
#[tokio::test]
async fn test_pre_exec_failure() {
let mut mock = MockExec::new();
// pre execute should be called and fail
mock.expect_pre_execute()
.once()
.returning(|| Err(anyhow::anyhow!("Error")));
// execute should never be called
mock.expect_execute().never().returning(|| Ok(()));
// post execute should never be called
mock.expect_post_execute().never().returning(|_r| Ok(()));
// run it
assert!(
mock.run().await.is_err(),
"Command::run should have returned an error on failed pre_execute"
);
}
/// An exec failure combined with post-exec propagation, should fail
#[tokio::test]
async fn test_exec_failure() {
let mut mock = MockExec::new();
// pre execute should be called and succeed
mock.expect_pre_execute().once().returning(|| Ok(()));
// execute should be called and fail
mock.expect_execute()
.once()
.returning(|| Err(anyhow!("Fail")));
// post execute should be called with an error
mock.expect_post_execute()
.withf(|r| r.is_err() && r.as_ref().is_err_and(|e| e.to_string().eq("Fail")))
.returning(|r| r);
// run it
assert!(
mock.run().await.is_err(),
"Command::run should have returned an error on failed execute/post-execute"
);
}
/// An exec failure should be able to be recovered by post exec
#[tokio::test]
async fn test_post_exec_recover() {
let mut mock = MockExec::new();
// pre execute should be called and succeed
mock.expect_pre_execute().once().returning(|| Ok(()));
// execute should be called and fail
mock.expect_execute()
.once()
.returning(|| Err(anyhow!("Fail")));
// post execute should be called, receive an error, and recover
mock.expect_post_execute()
.withf(|r| r.is_err() && r.as_ref().is_err_and(|e| e.to_string().eq("Fail")))
.returning(|_r| Ok(()));
// run it
assert!(
mock.run().await.is_ok(),
"Command::run should have recovered from error in post exec"
);
}
I wasn't aware that expectations were evaluated on drop()
, I had assumed that you configured the mock first, ran the code, and then after running, validate the assumptions.
from mockall.
Related Issues (20)
- Mocking an internal struct with external dependency HOT 7
- Capturing arguments from returning HOT 2
- Struggling to mock trait objects and make assertions on functions that take ownership of mock trait object HOT 4
- Mock trait with methods that return iterators HOT 8
- Mock Trait that is a composition of two other traits HOT 2
- Struct with different traits that has identically named methods HOT 1
- Can't apply `automock` to traits with default method implementions marked `#[inline]` HOT 1
- Remove ...
- Problem with mocking a trait which uses &Self HOT 1
- Mockall Double of struct in external crate HOT 2
- mocking struct & mockall_double::double not working as expected HOT 10
- Mocking with tokio::sync::Mutex, confused for std::sync::Mutex HOT 4
- Feature request: create a `spy!` macro to provide a transparent mock but that can be asserted upon. HOT 6
- Feature request: support for `const generics` in `mock!` and `automock` HOT 4
- How to bypass a mock for a particular test and call the original function HOT 3
- automock fails for method taking Option<&u32> HOT 5
- MSRV 1.77.0 TODO
- Mocking a function taking an FnMut closure incompatible with concretize HOT 2
- How to create a "dummy" mock where no expectations are required HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mockall.