mithril_common/test_utils/mock_extensions.rs
1//! A set of tools for working with `automock`
2//!
3//! IMPORTANT: To avoid polluting production code, those tools do not expose or reexpose any
4//! `automock`types, users need to add them themselves to their crates.
5use std::sync::Arc;
6
7/// Helper to create configured Mockall mock.
8///
9/// This allows creation of the mock in a dedicated block isolated from the remaining test method
10/// code.
11pub struct MockBuilder<M: Default> {
12 phantom: std::marker::PhantomData<M>,
13}
14
15impl<M: Default> MockBuilder<M> {
16 /// Create a new instance of the mock with the given configuration
17 ///
18 /// The type must be specified either:
19 /// ```
20 /// use mithril_common::test_utils::mock_extensions::MockBuilder;
21 /// # #[derive(Default)] struct MockType {};
22 ///
23 /// // from the builder generic
24 /// let mock = MockBuilder::<MockType>::configure(|mock| {});
25 ///
26 /// // or from the closure parameter
27 /// let mock = MockBuilder::configure(|mock: &mut MockType| {});
28 /// ```
29 pub fn configure(mock_config: impl FnOnce(&mut M)) -> Arc<M> {
30 let mut mock = M::default();
31 mock_config(&mut mock);
32 Arc::new(mock)
33 }
34}
35
36#[cfg(test)]
37mod tests {
38 use super::*;
39
40 #[mockall::automock]
41 trait TestTrait {
42 fn test_method(&self) -> String;
43 }
44
45 #[test]
46 fn using_mock_builder() {
47 // specify the type on the closure parameter
48 let mock = MockBuilder::configure(|mock: &mut MockTestTrait| {
49 mock.expect_test_method()
50 .returning(|| "test explicit type".to_string());
51 });
52 assert_eq!("test explicit type".to_string(), mock.test_method());
53
54 // specify the type on the builder generic
55 let mock = MockBuilder::<MockTestTrait>::configure(|mock| {
56 mock.expect_test_method().returning(|| "test turbofish".to_string());
57 });
58 assert_eq!("test turbofish".to_string(), mock.test_method());
59 }
60}