1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-04-25 08:53:01 +02:00

Add slide to show the Mockall crate in action (#1532)

As more and more Android teams start using Rust, the question of "How to do mocking?" has come up more frequently. Right now, we don't have a good answer to those teams, AOSP doesn't have any mocking framework available. That will change soon with the import of Mockall and this slide is part of the supporting documentation that we can point teams to.
This commit is contained in:
Martin Geisler 2023-12-01 15:36:06 +01:00 committed by GitHub
parent 3f7b6d4ad7
commit d0bab8302c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 191 additions and 0 deletions

112
Cargo.lock generated
View File

@ -468,6 +468,12 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "difflib"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
[[package]]
name = "digest"
version = "0.10.7"
@ -478,6 +484,12 @@ dependencies = [
"crypto-common",
]
[[package]]
name = "downcast"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1"
[[package]]
name = "dtoa"
version = "1.0.9"
@ -499,6 +511,12 @@ version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591"
[[package]]
name = "either"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "elasticlunr-rs"
version = "3.0.2"
@ -575,6 +593,15 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "float-cmp"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
dependencies = [
"num-traits",
]
[[package]]
name = "fnv"
version = "1.0.7"
@ -605,6 +632,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fragile"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa"
[[package]]
name = "fsevent-sys"
version = "4.1.0"
@ -1031,6 +1064,15 @@ dependencies = [
name = "iterators"
version = "0.1.0"
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.9"
@ -1258,6 +1300,33 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "mockall"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c84490118f2ee2d74570d114f3d0493cbf02790df303d2707606c3e14e07c96"
dependencies = [
"cfg-if",
"downcast",
"fragile",
"lazy_static",
"mockall_derive",
"predicates",
"predicates-tree",
]
[[package]]
name = "mockall_derive"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ce75669015c4f47b289fd4d4f56e894e4c96003ffdf3ac51313126f94c6cbb"
dependencies = [
"cfg-if",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "native-tls"
version = "0.2.11"
@ -1282,6 +1351,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
[[package]]
name = "normalize-line-endings"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
[[package]]
name = "normpath"
version = "1.1.1"
@ -1617,6 +1692,36 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "predicates"
version = "2.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd"
dependencies = [
"difflib",
"float-cmp",
"itertools",
"normalize-line-endings",
"predicates-core",
"regex",
]
[[package]]
name = "predicates-core"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174"
[[package]]
name = "predicates-tree"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf"
dependencies = [
"predicates-core",
"termtree",
]
[[package]]
name = "pretty_env_logger"
version = "0.5.0"
@ -2210,11 +2315,18 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "termtree"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
[[package]]
name = "testing"
version = "0.1.0"
dependencies = [
"googletest",
"mockall",
]
[[package]]

View File

@ -173,6 +173,7 @@
- [Other Types of Tests](testing/other.md)
- [Useful Crates](testing/useful-crates.md)
- [GoogleTest](testing/googletest.md)
- [Mocking](testing/mocking.md)
- [Compiler lints and Clippy](testing/lints.md)
- [Exercise: Luhn Algorithm](testing/exercise.md)
- [Solution](testing/solution.md)

View File

@ -10,9 +10,16 @@ crate-type = ["staticlib"]
path = "googletest.rs"
test = true
[[example]]
name = "mockall-example"
crate-type = ["staticlib"]
path = "mockall.rs"
test = true
[[bin]]
name = "luhn"
path = "exercise.rs"
[dependencies]
googletest = "0.10.0"
mockall = "0.11.4"

13
src/testing/mockall.rs Normal file
View File

@ -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);
}

58
src/testing/mocking.md Normal file
View File

@ -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.
- 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.
- Mockall is available for use in AOSP.
</details>