--- id: ad8a0732-733a-11ee-b2ab-13f1d6012322 title: | What the Rust Book didn't tell you about testing... status: ARCHIVED tags: - read-later - Newsletter date_added: 2023-10-25 10:30:35 url_omnivore: | https://omnivore.app/me/what-the-rust-book-didn-t-tell-you-about-testing-18b6707a120 url_original: | https://omnivore.app/no_url?q=1fed5fd7-7706-46cf-9947-927b26a77112 --- # What the Rust Book didn't tell you about testing... ## Highlights > [!quote] ㅤ > We want to test _get\_user_ without making real database queries. > > The solution is to mock the _Database_ trait and assert _execute\_query_ is called with the correct query. But how? > > We can use the [mockall crate](https://letsgetrusty.us6.list-manage.com/track/click?u=9f28b35c1658c447f3b962a54&id=00a07042b3&e=d0eb971086)! > > [source](https://omnivore.app/me/what-the-rust-book-didn-t-tell-you-about-testing-18b6707a120#f9650419-c778-4974-9da2-aabce209609f) > --- ## Original The Rust Book has an [entire chapter dedicated to testing](https://letsgetrusty.us6.list-manage.com/track/click?u=9f28b35c1658c447f3b962a54&id=a95a715235&e=d0eb971086), but it's missing a critical piece… What happens when your code needs to make API calls or database queries? Unit tests should be be fast, reliable, and deterministic. We don't want to make expensive calls that might fail for various reasons. Well here is some good news… we don't have to! We can use mocking to substitute real objects for mock objects and assert certain expectations… What's that? You want an example? Consider the following code… trait Database { fn execute_query(&self, query: String); } fn get_user(db: impl Database, id: i32) { let query = format!("SELECT * from Users where id={}", id); db.execute_query(query); } We want to test _get\_user_ without making real database queries. The solution is to mock the _Database_ trait and assert _execute\_query_ is called with the correct query. But how? We can use the [mockall crate](https://letsgetrusty.us6.list-manage.com/track/click?u=9f28b35c1658c447f3b962a54&id=00a07042b3&e=d0eb971086)! Here is how we would test _get\_user_… #[cfg(test)] use mockall::{automock, predicate::*}; #[cfg_attr(test, automock)] trait Database { fn execute_query(&self, query: String); } fn get_user(db: impl Database, id: i32) { let query = format!("SELECT * from Users where id={}", id); db.execute_query(query); } #[cfg(test)] mod tests { use super::*; #[test] fn get_user_executes_correct_query() { let mut mock_database = MockDatabase::new(); mock_database.expect_execute_query() .with(eq("SELECT * from Users where id=22".to_owned())) .once() .returning(|_x| ()); get_user(mock_database, 22); } } Boom! Now we have a unit test that's fast, reliable, and deterministic! If you haven't seen my [intro to testing in Rust video](https://letsgetrusty.us6.list-manage.com/track/click?u=9f28b35c1658c447f3b962a54&id=90d4167901&e=d0eb971086) make sure to check it out! Happy testing, and stay Rusty!