Skip to content

Commit

Permalink
Add reset functionality to mock server
Browse files Browse the repository at this point in the history
  • Loading branch information
alexliesenfeld committed Feb 27, 2024
1 parent 1ec91c8 commit 4d5284b
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 69 deletions.
74 changes: 43 additions & 31 deletions src/api/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,14 @@ impl MockServer {
server_adapter: Arc<dyn MockServerAdapter + Send + Sync>,
pool: Arc<Pool<Arc<dyn MockServerAdapter + Send + Sync>>>,
) -> Self {
with_retry(5, || server_adapter.ping())
.await
.expect("Cannot ping mock server.");
with_retry(5, || server_adapter.delete_all_mocks())
.await
.expect("Cannot reset mock server (task: delete mocks).");
with_retry(5, || server_adapter.delete_history())
.await
.expect("Cannot reset mock server (task: delete request history).");
Self {
let server = Self {
server_adapter: Some(server_adapter),
pool,
}
};

server.reset_async().await;

return server
}

/// Asynchronously connects to a remote mock server that is running in standalone mode using
Expand Down Expand Up @@ -214,8 +209,8 @@ impl MockServer {
/// mock.assert();
/// ```
pub fn mock<F>(&self, config_fn: F) -> Mock
where
F: FnOnce(When, Then),
where
F: FnOnce(When, Then),
{
self.mock_async(config_fn).join()
}
Expand All @@ -241,8 +236,8 @@ impl MockServer {
/// });
/// ```
pub async fn mock_async<'a, F>(&'a self, spec_fn: F) -> Mock<'a>
where
F: FnOnce(When, Then),
where
F: FnOnce(When, Then),
{
let mut req = Rc::new(Cell::new(RequestRequirements::new()));
let mut res = Rc::new(Cell::new(MockServerHttpResponse::new()));
Expand Down Expand Up @@ -273,38 +268,55 @@ impl MockServer {
}
}

/// Delete all [Mock](struct.Mock.html) object on the mock server and their call history.
/// Resets the mock server. More specifically, it deletes all [Mock](struct.Mock.html) objects
/// from the mock server and clears its request history.
///
/// **Example**:
/// ```
/// use isahc::get;
///
/// let server = httpmock::MockServer::start();
///
/// let mock = server.mock(|when, then| {
/// let mock = server.mock(|when, then| {
/// when.path("/hello");
/// then.status(200);
/// });
/// });
///
/// get(server.url("/hello")).unwrap();
/// let mut response = get(server.url("/hello")).unwrap();
/// assert_eq!(response.status(), 200);
///
/// mock.assert();
/// server.reset();
///
/// ...
/// let mut response = get(server.url("/hello")).unwrap();
/// assert_eq!(response.status(), 404);
/// ```
pub fn reset(&self) {
self.reset_async().join()
}

/// Resets the mock server. More specifically, it deletes all [Mock](struct.Mock.html) objects
/// from the mock server and clears its request history.
///
/// server.reset().await;
/// **Example**:
/// ```
/// use isahc::get;
/// async_std::task::block_on(async {
/// let server = httpmock::MockServer::start_async().await;
///
/// let mock = server.mock(|when, then| {
/// when.path("/hello");
/// then.status(404);
/// });
/// let mock = server.mock_async(|when, then| {
/// when.path("/hello");
/// then.status(200);
/// }).await;
///
/// // This will now return a 404
/// get(server.url("/hello")).unwrap();
/// let mut response = get(server.url("/hello")).unwrap();
/// assert_eq!(response.status(), 200);
///
/// mock.assert();
/// server.reset_async().await;
///
/// let mut response = get(server.url("/hello")).unwrap();
/// assert_eq!(response.status(), 404);
/// });
/// ```
pub async fn reset(&self) {
pub async fn reset_async(&self) {
if let Some(server_adapter) = &self.server_adapter {
with_retry(5, || server_adapter.delete_all_mocks())
.await
Expand Down
38 changes: 0 additions & 38 deletions tests/examples/getting_started_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,41 +51,3 @@ async fn async_getting_started_test() {
assert_eq!(response.status(), 200);
}

#[async_std::test]
async fn reset_test() {
// Start a lightweight mock server.
let server = MockServer::start();

// Create a mock on the server that will be reset later
server.mock(|when, then| {
when.method("GET")
.path("/translate")
.query_param("word", "hello");
then.status(500)
.header("content-type", "text/html; charset=UTF-8")
.body("Привет");
});

// Delete all previously created mocks
server.reset().await;

// Create a new mock that will replace the previous one
let hello_mock = server.mock(|when, then| {
when.method("GET")
.path("/translate")
.query_param("word", "hello");
then.status(200)
.header("content-type", "text/html; charset=UTF-8")
.body("Привет");
});

// Send an HTTP request to the mock server. This simulates your code.
let response = get(server.url("/translate?word=hello")).unwrap();

// Ensure the specified mock was called.
hello_mock.assert();

// Ensure the mock server did respond as specified.
assert_eq!(response.status(), 200);
}

2 changes: 2 additions & 0 deletions tests/examples/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod headers_tests;
mod json_body_tests;
mod multi_server_tests;
mod query_param_tests;
mod reset_tests;
mod showcase_tests;
mod string_body_tests;
mod url_matching_tests;
Expand All @@ -17,3 +18,4 @@ mod url_matching_tests;
mod standalone_tests;
#[cfg(feature = "remote")]
mod x_www_form_urlencoded_tests;

41 changes: 41 additions & 0 deletions tests/examples/reset_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use httpmock::prelude::*;
use isahc::{get, get_async};

Check warning on line 2 in tests/examples/reset_tests.rs

View workflow job for this annotation

GitHub Actions / build-remote-ubuntu-latest-1.70.0

unused import: `get_async`

Check warning on line 2 in tests/examples/reset_tests.rs

View workflow job for this annotation

GitHub Actions / build-ubuntu-latest-1.70.0

unused import: `get_async`

#[async_std::test]
async fn reset_server_test() {
// Start a lightweight mock server.
let server = MockServer::start();

// Create a mock on the server that will be reset later
server.mock(|when, then| {
when.method("GET")
.path("/translate")
.query_param("word", "hello");
then.status(500)
.header("content-type", "text/html; charset=UTF-8")
.body("Привет");
});

// Delete all previously created mocks
server.reset().await;

Check failure on line 20 in tests/examples/reset_tests.rs

View workflow job for this annotation

GitHub Actions / build-remote-ubuntu-latest-1.70.0

`()` is not a future

Check failure on line 20 in tests/examples/reset_tests.rs

View workflow job for this annotation

GitHub Actions / build-ubuntu-latest-1.70.0

`()` is not a future

// Create a new mock that will replace the previous one
let hello_mock = server.mock(|when, then| {
when.method("GET")
.path("/translate")
.query_param("word", "hello");
then.status(200)
.header("content-type", "text/html; charset=UTF-8")
.body("Привет");
});

// Send an HTTP request to the mock server. This simulates your code.
let response = get(server.url("/translate?word=hello")).unwrap();

// Ensure the specified mock was called.
hello_mock.assert();

// Ensure the mock server did respond as specified.
assert_eq!(response.status(), 200);
}

0 comments on commit 4d5284b

Please sign in to comment.