rustapi_testing/
expectation.rs

1use super::matcher::RequestMatcher;
2use bytes::Bytes;
3use http::{HeaderMap, StatusCode};
4
5/// An expectation for a request
6#[derive(Debug, Clone)]
7pub struct Expectation {
8    pub(crate) matcher: RequestMatcher,
9    pub(crate) response: MockResponse,
10    pub(crate) times: Times,
11    pub(crate) call_count: usize,
12}
13
14impl Expectation {
15    /// Create a new expectation
16    pub fn new(matcher: RequestMatcher) -> Self {
17        Self {
18            matcher,
19            response: MockResponse::default(),
20            times: Times::Once,
21            call_count: 0,
22        }
23    }
24
25    /// Set the response to match
26    pub fn respond_with(mut self, response: MockResponse) -> Self {
27        self.response = response;
28        self
29    }
30
31    /// Expect the request to be called exactly once
32    pub fn once(mut self) -> Self {
33        self.times = Times::Once;
34        self
35    }
36
37    /// Expect the request to be called exactly n times
38    pub fn times(mut self, n: usize) -> Self {
39        self.times = Times::Exactly(n);
40        self
41    }
42
43    /// Expect the request to be called at least once
44    pub fn at_least_once(mut self) -> Self {
45        self.times = Times::AtLeast(1);
46        self
47    }
48
49    /// Expect the request to never be called
50    pub fn never(mut self) -> Self {
51        self.times = Times::Exactly(0);
52        self
53    }
54}
55
56/// Define how many times an expectation should be matched
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58pub enum Times {
59    Once,
60    Exactly(usize),
61    AtLeast(usize),
62    AtMost(usize),
63    Any,
64}
65
66/// A mocked response
67#[derive(Debug, Clone)]
68pub struct MockResponse {
69    pub(crate) status: StatusCode,
70    pub(crate) headers: HeaderMap,
71    pub(crate) body: Bytes,
72}
73
74impl Default for MockResponse {
75    fn default() -> Self {
76        Self {
77            status: StatusCode::OK,
78            headers: HeaderMap::new(),
79            body: Bytes::new(),
80        }
81    }
82}
83
84impl MockResponse {
85    pub fn new() -> Self {
86        Self::default()
87    }
88
89    pub fn status(mut self, status: StatusCode) -> Self {
90        self.status = status;
91        self
92    }
93
94    pub fn header(mut self, key: &str, value: &str) -> Self {
95        self.headers.insert(
96            http::header::HeaderName::from_bytes(key.as_bytes()).unwrap(),
97            http::header::HeaderValue::from_str(value).unwrap(),
98        );
99        self
100    }
101
102    pub fn body(mut self, body: impl Into<Bytes>) -> Self {
103        self.body = body.into();
104        self
105    }
106
107    pub fn json(mut self, body: impl serde::Serialize) -> Self {
108        self.headers.insert(
109            http::header::CONTENT_TYPE,
110            http::header::HeaderValue::from_static("application/json"),
111        );
112        self.body = serde_json::to_vec(&body).unwrap().into();
113        self
114    }
115}