1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/// Implements `Clone` for mock object.
///
/// Sometimes it is needed for mock to be clonable. Say you have
/// following trait and function accepting this trait you need to test:
///
/// ```rust,ignore
/// #[derive(Mock)]
/// pub trait A {
///     fn foo(&self, a: u32);
/// }
///
/// fn target<AC: A + Clone>(a: AC) {
///     let clone = a.clone();
///     clone.foo(2);
/// }
/// ```
///
/// There are two forms of macro invokation.
/// First one with mock struct name as single argument mocks `clone` method,
/// so you may specify arbitrary expectations and reactions on it:
///
/// ```rust,ignore
/// mock_clone!(AMock);
///
/// #[test]
/// fn test_clone_mock() {
///     let scenario = Scenario::new();
///     let mock = scenario.create_mock_for::<A>();
///     let mock_clone = scenario.create_mock_for::<A>();
///
///     scenario.expect(mock_clone.foo_call(2).and_return_default().times(1));
///     scenario.expect(mock.clone_call().and_return(mock_clone));
///
///     target(mock);
/// }
/// ```
///
/// Please note that you must specify mock name, not name of mocked trait. This is
/// limitation of current macro_rules system. If you mocked trait using `derive`
/// attribute, then just append "Mock" to trait name.
///
/// Second form accepts one additional parameter - strategy, which specifies how
/// cloned mock should behave. Currently there is only one strategy - "share_expectations",
/// which means that all mock clones are indistinguishable and expectations set on one
/// of them may be satisfied by calls made on another one. This is very useful when
/// mocked trait behaves like handle to some real implementation.
///
/// ```rust,ignore
/// mock_clone!(AMock, share_expectations);
///
/// #[test]
/// fn test_shared() {
///     let scenario = Scenario::new();
///     let mock = scenario.create_mock_for::<A>();
///
///     scenario.expect(mock.foo_call(2).and_return_default().times(1));
///
///     target(mock);
/// }
/// ```
#[macro_export]
macro_rules! mock_clone {
    ($mock_name:ident) => {
        #[cfg(test)]
        impl Clone for $mock_name {
            fn clone(&self) -> Self {
                let method_data =
                    ::mockers::MethodData{mock_id: self.mock_id,
                                          mock_type_id: 0usize,
                                          method_name: "clone",};
                let action = self.scenario.borrow_mut().verify0(method_data);
                action.call()
            }
        }

        impl $mock_name {
            #[allow(dead_code)]
            pub fn clone_call(&self)
             -> ::mockers::CallMatch0<Self> {
                ::mockers::CallMatch0::new(self.mock_id, 0usize, "clone")
            }
        }
    };

    ($mock_name:ident, share_expectations) => {
        #[cfg(test)]
        impl Clone for $mock_name {
            fn clone(&self) -> Self {
                use $crate::Mock;
                $mock_name::new(self.mock_id, self.scenario.clone())
            }
        }
    };
}