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}