-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Add slide to show the Mockall crate in action #1532
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
use std::time::Duration; | ||
|
||
#[mockall::automock] | ||
pub trait Pet { | ||
fn is_hungry(&self, since_last_meal: Duration) -> bool; | ||
} | ||
|
||
#[test] | ||
fn test_robot_pet() { | ||
let mut mock_dog = MockPet::new(); | ||
mock_dog.expect_is_hungry().return_const(true); | ||
assert_eq!(mock_dog.is_hungry(Duration::from_secs(10)), true); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
--- | ||
minutes: 5 | ||
--- | ||
|
||
# Mocking | ||
|
||
If you want to do mocking, we recommend [Mockall]. You need to refactor your | ||
code to use traits, which you can then quickly mock: | ||
|
||
```rust,ignore | ||
{{#include mockall.rs}} | ||
``` | ||
|
||
[Mockall]: https://docs.rs/mockall/ | ||
|
||
<details> | ||
|
||
- Note that *mocking is controversial*: mocks allow you to completely isolate a | ||
test from its dependencies. The immediate result is faster and more stable | ||
test execution. On the other hand, the mocks can be configured wrongly and | ||
return output different from what the real dependencies would do. | ||
|
||
If at all possible, it is recommended that you use the real dependencies. As | ||
an example, many databases allow you to configure an in-memory backend. This | ||
means that you get the correct behavior in your tests, plus they are fast and | ||
will automatically clean up after themselves. | ||
|
||
Similarly, many web frameworks allow you to start an in-process server which | ||
binds to a random port on `localhost`. Always prefer this over mocking away | ||
the framework since it helps you test your code in the real environment. | ||
Comment on lines
+18
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems out of context here -- if students are asking how to use mocks in Rust, they are probably more focused on the "in Rust" part and do not want to be told that they shouldn't be using mocks. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was the first thing @qwandor brought up and it's what our internal guidelines say. However, the advice is not specific to Google or Android, it's a generic argument about using mocking in any language or environment. I think it's good to note, even for non-Googlers: I was not aware of the "controversy" until reading more about it — I had been happily mocking for years in my Python work. What could improve it further (in my opinion) would be a link to an article about the problems with mocking. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I still want to keep it short, though, just in the interest of overall course length. I think this lengthy speaker note encourages a digression into the relative merits of various testing strategies, which will probably generate questions and comments from students, and suddenly we've been on this slide for 15 minutes. I agree that an article would be great, but maybe this could be moved to "More to Explore"? At any rate, LGTM. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Fair point! I was not thinking that the instructor would go through all the pros and cons — I guess I was writing this bullet point more for the people who will read the slide by themselves. The problem of multiple personas reading the slides is tricky... as we've discussed before 😄 It just occurred to me that we could create more sections in the notes (and first rename them to "Notes"): <details>
### Speaker
- Make sure to mention X and Y.
- Try removing `x`, note the compilation error.
### Participants
- The concept of Foo was originally introduced in C++ as Bar. See Wikipedia.
- If you want to explore more, then try ...
</details> Basically an extension of the "More to Explore" headings we've added a few places. |
||
|
||
- Mockall is not part of the Rust Playground, so you need to run this example in | ||
a local environment. Use `cargo add mockall` to quickly add Mockall to an | ||
existing Cargo project. | ||
|
||
- Mockall has a lot more functionality. In particular, you can set up | ||
expectations which depend on the arguments passed: | ||
|
||
```rust,ignore | ||
let mut mock_cat = MockPet::new(); | ||
mock_cat | ||
.expect_is_hungry() | ||
.with(mockall::predicate::gt(Duration::from_secs(3 * 3600))) | ||
.return_const(true); | ||
mock_cat | ||
.expect_is_hungry() | ||
.return_const(true); | ||
assert_eq!(mock_cat.is_hungry(Duration::from_secs(1 * 3600)), false); | ||
assert_eq!(mock_cat.is_hungry(Duration::from_secs(5 * 3600)), true); | ||
``` | ||
|
||
- You can use `.times(n)` to limit the number of times a mock method can be | ||
called to `n` --- the mock will automatically panic when dropped if this isn't | ||
satisfied. | ||
mgeisler marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
- Mockall is available for use in AOSP. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not strictly true today, but it should be true by ~next week. |
||
|
||
</details> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
..or something to that effect. I think the existing text implies "mockall is how people do test mocks in Rust", and that's not accurate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did a survey and from what I can tell, Mockall is vastly more used than any other mocking library right now:
Most libraries haven't been updated in a few years and most of them have very few reverse dependencies.
Of course Mockall isn't the end all of mocking, so a new library could be made which is even better. But right it's the one we will recommend to our engineers in Android.
At the end of the day, the course here is written for Android engineers. I've tried my best to take out the Android-specific parts and make as much as it generic. I think the advise here is also generic enough for this section.
However, let us add a note on the slide (and perhaps somewhere in the beginning) to say that the material here is an opinionated guide to Rust. It tried to be fair and generic, but it is sponsored by Google, and it will recommend tools useful today to Android and Google engineers. Does that sound fair?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, thanks for that analysis of the libraries! A few search results suggested a much wider range of options. Given that information, this slide makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I will add a note explaining that the recommendations on the slide is current at of now and apply directly to Android. They might also apply to others, but as you point out, there are other options out there!