Skip to main content

wae_testing/
mock.rs

1//! Mock 工具模块
2
3use crate::error::{TestingError, TestingResult};
4use parking_lot::RwLock;
5use std::sync::Arc;
6
7/// Mock 调用记录
8#[derive(Debug, Clone)]
9pub struct MockCall {
10    /// 调用参数 (JSON 序列化)
11    pub args: Vec<String>,
12    /// 调用时间戳
13    pub timestamp: std::time::Instant,
14}
15
16/// Mock 返回结果
17#[derive(Debug, Clone)]
18pub enum MockResult<T> {
19    /// 返回指定值
20    Return(T),
21    /// 返回错误
22    Error(String),
23    /// 根据调用次数返回不同结果
24    Sequence(Vec<T>),
25}
26
27impl<T: Clone> MockResult<T> {
28    /// 创建返回值
29    pub fn return_value(value: T) -> Self {
30        MockResult::Return(value)
31    }
32
33    /// 创建错误返回
34    pub fn error(msg: impl Into<String>) -> Self {
35        MockResult::Error(msg.into())
36    }
37
38    /// 创建序列返回
39    pub fn sequence(values: Vec<T>) -> Self {
40        MockResult::Sequence(values)
41    }
42}
43
44/// Mock 期望配置
45#[derive(Debug, Default)]
46pub struct MockExpectation {
47    /// 期望的调用次数
48    pub expected_calls: Option<usize>,
49    /// 描述信息
50    pub description: Option<String>,
51}
52
53impl MockExpectation {
54    /// 创建新的期望配置
55    pub fn new() -> Self {
56        Self::default()
57    }
58
59    /// 设置期望调用次数
60    pub fn times(mut self, count: usize) -> Self {
61        self.expected_calls = Some(count);
62        self
63    }
64
65    /// 设置描述
66    pub fn description(mut self, desc: impl Into<String>) -> Self {
67        self.description = Some(desc.into());
68        self
69    }
70}
71
72/// Mock 行为 trait
73pub trait Mock: Send + Sync {
74    /// 获取调用记录
75    fn calls(&self) -> Vec<MockCall>;
76
77    /// 获取调用次数
78    fn call_count(&self) -> usize;
79
80    /// 验证期望
81    fn verify(&self) -> TestingResult<()>;
82
83    /// 重置 Mock 状态
84    fn reset(&self);
85}
86
87/// Mock 构建器
88pub struct MockBuilder<T> {
89    result: Option<MockResult<T>>,
90    expectation: MockExpectation,
91    calls: Arc<RwLock<Vec<MockCall>>>,
92}
93
94impl<T: Clone + Send + Sync + 'static> MockBuilder<T> {
95    /// 创建新的 Mock 构建器
96    pub fn new() -> Self {
97        Self { result: None, expectation: MockExpectation::default(), calls: Arc::new(RwLock::new(Vec::new())) }
98    }
99
100    /// 设置返回值
101    pub fn return_value(mut self, value: T) -> Self {
102        self.result = Some(MockResult::return_value(value));
103        self
104    }
105
106    /// 设置错误返回
107    pub fn error(mut self, msg: impl Into<String>) -> Self {
108        self.result = Some(MockResult::error(msg));
109        self
110    }
111
112    /// 设置序列返回
113    pub fn sequence(mut self, values: Vec<T>) -> Self {
114        self.result = Some(MockResult::sequence(values));
115        self
116    }
117
118    /// 设置期望
119    pub fn expect(mut self, expectation: MockExpectation) -> Self {
120        self.expectation = expectation;
121        self
122    }
123
124    /// 构建可执行的 Mock
125    pub fn build(self) -> MockFn<T> {
126        MockFn {
127            result: self.result,
128            expectation: self.expectation,
129            calls: self.calls,
130            sequence_index: Arc::new(RwLock::new(0)),
131        }
132    }
133}
134
135impl<T: Clone + Send + Sync + 'static> Default for MockBuilder<T> {
136    fn default() -> Self {
137        Self::new()
138    }
139}
140
141/// 可执行的 Mock 函数
142pub struct MockFn<T> {
143    result: Option<MockResult<T>>,
144    expectation: MockExpectation,
145    calls: Arc<RwLock<Vec<MockCall>>>,
146    sequence_index: Arc<RwLock<usize>>,
147}
148
149impl<T: Clone> MockFn<T> {
150    /// 执行 Mock 调用
151    pub fn call(&self, args: Vec<String>) -> TestingResult<T> {
152        {
153            let mut calls = self.calls.write();
154            calls.push(MockCall { args, timestamp: std::time::Instant::now() });
155        }
156
157        match &self.result {
158            Some(MockResult::Return(v)) => Ok(v.clone()),
159            Some(MockResult::Error(e)) => Err(TestingError::MockError(e.clone())),
160            Some(MockResult::Sequence(values)) => {
161                let mut idx = self.sequence_index.write();
162                if *idx < values.len() {
163                    let value = values[*idx].clone();
164                    *idx += 1;
165                    Ok(value)
166                }
167                else {
168                    Err(TestingError::MockError("Mock sequence exhausted".to_string()))
169                }
170            }
171            None => Err(TestingError::MockError("No mock result configured".to_string())),
172        }
173    }
174
175    /// 异步执行 Mock 调用
176    pub async fn call_async(&self, args: Vec<String>) -> TestingResult<T> {
177        self.call(args)
178    }
179}
180
181impl<T: Clone + Send + Sync + 'static> Mock for MockFn<T> {
182    fn calls(&self) -> Vec<MockCall> {
183        self.calls.read().clone()
184    }
185
186    fn call_count(&self) -> usize {
187        self.calls.read().len()
188    }
189
190    fn verify(&self) -> TestingResult<()> {
191        let actual_calls = self.call_count();
192
193        if let Some(expected) = self.expectation.expected_calls
194            && actual_calls != expected
195        {
196            return Err(TestingError::AssertionFailed(format!("Expected {} calls, but got {}", expected, actual_calls)));
197        }
198
199        Ok(())
200    }
201
202    fn reset(&self) {
203        let mut calls = self.calls.write();
204        calls.clear();
205        let mut idx = self.sequence_index.write();
206        *idx = 0;
207    }
208}
209
210/// 验证 Mock 期望
211pub fn verify<M: Mock>(mock: &M) -> TestingResult<()> {
212    mock.verify()
213}