1use crate::{Executor, OrmResult};
2use chopin_pg::Row;
3use std::collections::VecDeque;
4
5pub struct MockExecutor {
9 pub executed_queries: Vec<(String, usize)>,
11 mocked_results: VecDeque<Vec<Row>>,
12}
13
14impl MockExecutor {
15 pub fn new() -> Self {
16 Self {
17 executed_queries: Vec::new(),
18 mocked_results: VecDeque::new(),
19 }
20 }
21
22 pub fn push_result(&mut self, rows: Vec<Row>) {
24 self.mocked_results.push_back(rows);
25 }
26
27 pub fn remaining_results(&self) -> usize {
29 self.mocked_results.len()
30 }
31
32 pub fn reset(&mut self) {
34 self.executed_queries.clear();
35 self.mocked_results.clear();
36 }
37}
38
39impl Default for MockExecutor {
40 fn default() -> Self {
41 Self::new()
42 }
43}
44
45impl Executor for MockExecutor {
46 fn execute(&mut self, query: &str, params: &[&dyn chopin_pg::types::ToSql]) -> OrmResult<u64> {
47 self.executed_queries
48 .push((query.to_string(), params.len()));
49 Ok(1)
50 }
51
52 fn query(
53 &mut self,
54 query: &str,
55 params: &[&dyn chopin_pg::types::ToSql],
56 ) -> OrmResult<Vec<Row>> {
57 self.executed_queries
58 .push((query.to_string(), params.len()));
59 if let Some(rows) = self.mocked_results.pop_front() {
60 Ok(rows)
61 } else {
62 Ok(vec![])
63 }
64 }
65}
66
67#[macro_export]
71macro_rules! mock_row {
72 ( $( $name:expr => $val:expr ),* $(,)? ) => {
73 {
74 use chopin_pg::types::ToParam;
75 let mut names = Vec::new();
76 let mut vals: Vec<chopin_pg::PgValue> = Vec::new();
77 $(
78 names.push($name);
79 vals.push($val.to_param());
80 )*
81 chopin_pg::Row::mock(&names, &vals)
82 }
83 };
84}
85
86#[cfg(test)]
87#[allow(dead_code)]
88mod tests {
89 use super::*;
90 use crate as chopin_orm;
91 use crate::{Model, builder::ColumnTrait};
92
93 #[derive(Model, Debug, Clone, PartialEq)]
94 #[model(table_name = "tester")]
95 pub struct Tester {
96 #[model(primary_key)]
97 pub id: i32,
98 pub name: String,
99 }
100 impl crate::Validate for Tester {}
101
102 #[test]
103 fn test_mock_executor() {
104 let mut mock = MockExecutor::new();
105 mock.push_result(vec![
106 mock_row!("id" => 1, "name" => "Alice"),
107 mock_row!("id" => 2, "name" => "Bob"),
108 ]);
109
110 let results = Tester::find()
111 .filter(TesterColumn::id.gt(0))
112 .all(&mut mock)
113 .unwrap();
114
115 assert_eq!(results.len(), 2);
116 assert_eq!(results[0].name, "Alice");
117 assert_eq!(results[1].name, "Bob");
118 assert_eq!(mock.executed_queries.len(), 1);
119 assert!(
120 mock.executed_queries[0]
121 .0
122 .contains("SELECT id, name FROM tester WHERE id > $1")
123 );
124 }
125}