diff --git a/src/lib.rs b/src/lib.rs index d2d70c9..f9fc351 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -716,7 +716,8 @@ pub struct Mock { body: Matcher, response: Response, hits: usize, - expected_hits: usize, + expected_hits_at_least: Option, + expected_hits_at_most: Option, is_remote: bool, } @@ -730,7 +731,8 @@ impl Mock { body: Matcher::Any, response: Response::default(), hits: 0, - expected_hits: 1, + expected_hits_at_least: None, + expected_hits_at_most: None, is_remote: false, } } @@ -933,8 +935,36 @@ impl Mock { /// Defaults to 1 request. /// pub fn expect(mut self, hits: usize) -> Self { - self.expected_hits = hits; + self.expected_hits_at_least = Some(hits); + self.expected_hits_at_most = Some(hits); + self + } + + /// + /// Sets the minimal amount of requests that this mock is supposed to receive. + /// This is only enforced when calling the `assert` method. + /// + pub fn expect_at_least(mut self, hits: usize) -> Self { + self.expected_hits_at_least = Some(hits); + if self.expected_hits_at_most.is_some() + && self.expected_hits_at_most < self.expected_hits_at_least + { + self.expected_hits_at_most = None; + } + self + } + /// + /// Sets the maximal amount of requests that this mock is supposed to receive. + /// This is only enforced when calling the `assert` method. + /// + pub fn expect_at_most(mut self, hits: usize) -> Self { + self.expected_hits_at_most = Some(hits); + if self.expected_hits_at_least.is_some() + && self.expected_hits_at_least > self.expected_hits_at_most + { + self.expected_hits_at_least = None; + } self } @@ -950,11 +980,28 @@ impl Mock { if let Some(remote_mock) = state.mocks.iter().find(|mock| mock.id == self.id) { opt_hits = Some(remote_mock.hits); - - let mut message = format!( - "\n> Expected {} request(s) to:\n{}\n...but received {}\n\n", - self.expected_hits, self, remote_mock.hits - ); + let mut message = match (self.expected_hits_at_least, self.expected_hits_at_most) { + (Some(min), Some(max)) if min == max => format!( + "\n> Expected {} request(s) to:\n{}\n...but received {}\n\n", + min, self, remote_mock.hits + ), + (Some(min), Some(max)) => format!( + "\n> Expected between {} and {} request(s) to:\n{}\n...but received {}\n\n", + min, max, self, remote_mock.hits + ), + (Some(min), None) => format!( + "\n> Expected at least {} request(s) to:\n{}\n...but received {}\n\n", + min, self, remote_mock.hits + ), + (None, Some(max)) => format!( + "\n> Expected at most {} request(s) to:\n{}\n...but received {}\n\n", + max, self, remote_mock.hits + ), + (None, None) => format!( + "\n> Expected 1 request(s) to:\n{}\n...but received {}\n\n", + self, remote_mock.hits + ), + }; if let Some(last_request) = state.unmatched_requests.last() { message.push_str(&format!( @@ -971,7 +1018,16 @@ impl Mock { } match (opt_hits, opt_message) { - (Some(hits), Some(message)) => assert_eq!(self.expected_hits, hits, "{}", message), + (Some(hits), Some(message)) => assert!( + match (self.expected_hits_at_least, self.expected_hits_at_most) { + (Some(min), Some(max)) => hits >= min && hits <= max, + (Some(min), None) => hits >= min, + (None, Some(max)) => hits <= max, + (None, None) => hits == 1, + }, + "{}", + message + ), _ => panic!("Could not retrieve enough information about the remote mock."), } } diff --git a/tests/lib.rs b/tests/lib.rs index 8193aeb..de16f2d 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -880,6 +880,130 @@ fn test_expect() { mock.assert(); } +#[test] +fn test_expect_at_least_and_at_most() { + let mock = mock("GET", "/hello") + .expect_at_least(3) + .expect_at_most(6) + .create(); + + request("GET /hello", ""); + request("GET /hello", ""); + request("GET /hello", ""); + request("GET /hello", ""); + request("GET /hello", ""); + + mock.assert(); +} + +#[test] +fn test_expect_at_least() { + let mock = mock("GET", "/hello").expect_at_least(3).create(); + + request("GET /hello", ""); + request("GET /hello", ""); + request("GET /hello", ""); + + mock.assert(); +} + +#[test] +fn test_expect_at_least_more() { + let mock = mock("GET", "/hello").expect_at_least(3).create(); + + request("GET /hello", ""); + request("GET /hello", ""); + request("GET /hello", ""); + request("GET /hello", ""); + + mock.assert(); +} + +#[test] +fn test_expect_at_most_with_needed_requests() { + let mock = mock("GET", "/hello").expect_at_most(3).create(); + + request("GET /hello", ""); + request("GET /hello", ""); + request("GET /hello", ""); + + mock.assert(); +} + +#[test] +fn test_expect_at_most_with_few_requests() { + let mock = mock("GET", "/hello").expect_at_most(3).create(); + + request("GET /hello", ""); + request("GET /hello", ""); + + mock.assert(); +} + +#[test] +#[should_panic( + expected = "\n> Expected at least 3 request(s) to:\n\r\nGET /hello\r\n\n...but received 2\n" +)] +fn test_assert_panics_expect_at_least_with_too_few_requests() { + let mock = mock("GET", "/hello").expect_at_least(3).create(); + + request("GET /hello", ""); + request("GET /hello", ""); + + mock.assert(); +} + +#[test] +#[should_panic( + expected = "\n> Expected at most 3 request(s) to:\n\r\nGET /hello\r\n\n...but received 4\n" +)] +fn test_assert_panics_expect_at_most_with_too_many_requests() { + let mock = mock("GET", "/hello").expect_at_most(3).create(); + + request("GET /hello", ""); + request("GET /hello", ""); + request("GET /hello", ""); + request("GET /hello", ""); + + mock.assert(); +} + +#[test] +#[should_panic( + expected = "\n> Expected between 3 and 5 request(s) to:\n\r\nGET /hello\r\n\n...but received 2\n" +)] +fn test_assert_panics_expect_at_least_and_at_most_with_too_few_requests() { + let mock = mock("GET", "/hello") + .expect_at_least(3) + .expect_at_most(5) + .create(); + + request("GET /hello", ""); + request("GET /hello", ""); + + mock.assert(); +} + +#[test] +#[should_panic( + expected = "\n> Expected between 3 and 5 request(s) to:\n\r\nGET /hello\r\n\n...but received 6\n" +)] +fn test_assert_panics_expect_at_least_and_at_most_with_too_many_requests() { + let mock = mock("GET", "/hello") + .expect_at_least(3) + .expect_at_most(5) + .create(); + + request("GET /hello", ""); + request("GET /hello", ""); + request("GET /hello", ""); + request("GET /hello", ""); + request("GET /hello", ""); + request("GET /hello", ""); + + mock.assert(); +} + #[test] #[should_panic(expected = "\n> Expected 1 request(s) to:\n\r\nGET /hello\r\n\n...but received 0\n")] fn test_assert_panics_if_no_request_was_performed() {