mockforge_sdk/verification.rs
1//! Verification API for MockForge SDK
2//!
3//! Provides methods to verify that specific requests were made (or not made)
4//! during test execution.
5
6use crate::Error;
7use mockforge_core::{
8 request_logger::get_global_logger, verify_at_least, verify_never, verify_requests,
9 verify_sequence, VerificationCount, VerificationRequest, VerificationResult,
10};
11
12/// Extension trait for verification methods on MockServer
13pub trait Verification {
14 /// Verify requests against a pattern and count assertion
15 ///
16 /// # Example
17 ///
18 /// ```rust,no_run
19 /// use mockforge_sdk::MockServer;
20 /// use mockforge_sdk::verification::Verification;
21 /// use mockforge_core::verification::{VerificationRequest, VerificationCount};
22 ///
23 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
24 /// let mut server = MockServer::new().port(3000).start().await?;
25 ///
26 /// // Make some requests...
27 ///
28 /// let pattern = VerificationRequest {
29 /// method: Some("GET".to_string()),
30 /// path: Some("/api/users".to_string()),
31 /// query_params: std::collections::HashMap::new(),
32 /// headers: std::collections::HashMap::new(),
33 /// body_pattern: None,
34 /// };
35 ///
36 /// let result = server.verify(&pattern, VerificationCount::Exactly(3)).await?;
37 /// assert!(result.matched, "Expected GET /api/users to be called exactly 3 times");
38 /// # Ok(())
39 /// # }
40 /// ```
41 async fn verify(
42 &self,
43 pattern: &VerificationRequest,
44 expected: VerificationCount,
45 ) -> Result<VerificationResult, Error>;
46
47 /// Verify that a request was never made
48 ///
49 /// # Example
50 ///
51 /// ```rust,no_run
52 /// use mockforge_sdk::MockServer;
53 /// use mockforge_sdk::verification::Verification;
54 /// use mockforge_core::verification::VerificationRequest;
55 ///
56 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
57 /// let mut server = MockServer::new().port(3000).start().await?;
58 ///
59 /// // Make some requests...
60 ///
61 /// let pattern = VerificationRequest {
62 /// method: Some("DELETE".to_string()),
63 /// path: Some("/api/users/1".to_string()),
64 /// query_params: std::collections::HashMap::new(),
65 /// headers: std::collections::HashMap::new(),
66 /// body_pattern: None,
67 /// };
68 ///
69 /// let result = server.verify_never(&pattern).await?;
70 /// assert!(result.matched, "Expected DELETE /api/users/1 to never be called");
71 /// # Ok(())
72 /// # }
73 /// ```
74 async fn verify_never(
75 &self,
76 pattern: &VerificationRequest,
77 ) -> Result<VerificationResult, Error>;
78
79 /// Verify that a request was made at least N times
80 ///
81 /// # Example
82 ///
83 /// ```rust,no_run
84 /// use mockforge_sdk::MockServer;
85 /// use mockforge_sdk::verification::Verification;
86 /// use mockforge_core::verification::VerificationRequest;
87 ///
88 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
89 /// let mut server = MockServer::new().port(3000).start().await?;
90 ///
91 /// // Make some requests...
92 ///
93 /// let pattern = VerificationRequest {
94 /// method: Some("POST".to_string()),
95 /// path: Some("/api/orders".to_string()),
96 /// query_params: std::collections::HashMap::new(),
97 /// headers: std::collections::HashMap::new(),
98 /// body_pattern: None,
99 /// };
100 ///
101 /// let result = server.verify_at_least(&pattern, 2).await?;
102 /// assert!(result.matched, "Expected POST /api/orders to be called at least 2 times");
103 /// # Ok(())
104 /// # }
105 /// ```
106 async fn verify_at_least(
107 &self,
108 pattern: &VerificationRequest,
109 min: usize,
110 ) -> Result<VerificationResult, Error>;
111
112 /// Verify that requests occurred in a specific sequence
113 ///
114 /// # Example
115 ///
116 /// ```rust,no_run
117 /// use mockforge_sdk::MockServer;
118 /// use mockforge_sdk::verification::Verification;
119 /// use mockforge_core::verification::VerificationRequest;
120 ///
121 /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
122 /// let mut server = MockServer::new().port(3000).start().await?;
123 ///
124 /// // Make some requests in sequence...
125 ///
126 /// let patterns = vec![
127 /// VerificationRequest {
128 /// method: Some("POST".to_string()),
129 /// path: Some("/api/users".to_string()),
130 /// query_params: std::collections::HashMap::new(),
131 /// headers: std::collections::HashMap::new(),
132 /// body_pattern: None,
133 /// },
134 /// VerificationRequest {
135 /// method: Some("GET".to_string()),
136 /// path: Some("/api/users/1".to_string()),
137 /// query_params: std::collections::HashMap::new(),
138 /// headers: std::collections::HashMap::new(),
139 /// body_pattern: None,
140 /// },
141 /// ];
142 ///
143 /// let result = server.verify_sequence(&patterns).await?;
144 /// assert!(result.matched, "Expected requests to occur in sequence");
145 /// # Ok(())
146 /// # }
147 /// ```
148 async fn verify_sequence(
149 &self,
150 patterns: &[VerificationRequest],
151 ) -> Result<VerificationResult, Error>;
152}
153
154impl Verification for crate::server::MockServer {
155 async fn verify(
156 &self,
157 pattern: &VerificationRequest,
158 expected: VerificationCount,
159 ) -> Result<VerificationResult, Error> {
160 let logger = get_global_logger()
161 .ok_or_else(|| Error::General("Request logger not initialized".to_string()))?;
162
163 Ok(verify_requests(logger, pattern, expected).await)
164 }
165
166 async fn verify_never(
167 &self,
168 pattern: &VerificationRequest,
169 ) -> Result<VerificationResult, Error> {
170 let logger = get_global_logger()
171 .ok_or_else(|| Error::General("Request logger not initialized".to_string()))?;
172
173 Ok(verify_never(logger, pattern).await)
174 }
175
176 async fn verify_at_least(
177 &self,
178 pattern: &VerificationRequest,
179 min: usize,
180 ) -> Result<VerificationResult, Error> {
181 let logger = get_global_logger()
182 .ok_or_else(|| Error::General("Request logger not initialized".to_string()))?;
183
184 Ok(verify_at_least(logger, pattern, min).await)
185 }
186
187 async fn verify_sequence(
188 &self,
189 patterns: &[VerificationRequest],
190 ) -> Result<VerificationResult, Error> {
191 let logger = get_global_logger()
192 .ok_or_else(|| Error::General("Request logger not initialized".to_string()))?;
193
194 Ok(verify_sequence(logger, patterns).await)
195 }
196}