pub struct MockServer(/* private fields */);
Expand description
An HTTP web-server running in the background to behave as one of your dependencies using Mock
s
for testing purposes.
Each instance of MockServer
is fully isolated: MockServer::start
takes care of finding a random port
available on your local machine which is assigned to the new MockServer
.
You can use MockServer::builder
if you need to specify custom configuration - e.g.
run on a specific port or disable request recording.
§Best practices
You should use one instance of MockServer
for each REST API that your application interacts
with and needs mocking for testing purposes.
To ensure full isolation and no cross-test interference, MockServer
s shouldn’t be
shared between tests. Instead, MockServer
s should be created in the test where they are used.
When using a Mock
within a test helper function, consider using MockServer::register_as_scoped
instead of MockServer::register
.
You can register as many Mock
s as your scenario requires on a MockServer
.
Implementations§
Source§impl MockServer
impl MockServer
Sourcepub fn builder() -> MockServerBuilder
pub fn builder() -> MockServerBuilder
You can use MockServer::builder
if you need to specify custom configuration - e.g.
run on a specific port or disable request recording.
If this is not your case, use MockServer::start
.
Sourcepub async fn start() -> Self
pub async fn start() -> Self
Start a new instance of a MockServer
listening on a random port.
Each instance of MockServer
is fully isolated: start
takes care of finding a random port
available on your local machine which is assigned to the new MockServer
.
You should use one instance of MockServer
for each REST API that your application interacts
with and needs mocking for testing purposes.
§Example:
use wiremock::{MockServer, Mock, ResponseTemplate};
use wiremock::matchers::method;
#[async_std::main]
async fn main() {
// Arrange
let mock_server_one = MockServer::start().await;
let mock_server_two = MockServer::start().await;
assert!(mock_server_one.address() != mock_server_two.address());
let mock = Mock::given(method("GET")).respond_with(ResponseTemplate::new(200));
// Registering the mock with the first mock server - it's now effective!
// But it *won't* be used by the second mock server!
mock_server_one.register(mock).await;
// Act
let status = surf::get(&mock_server_one.uri())
.await
.unwrap()
.status();
assert_eq!(status, 200);
// This would have matched our mock, but we haven't registered it for `mock_server_two`!
// Hence it returns a 404, the default response when no mocks matched on the mock server.
let status = surf::get(&mock_server_two.uri())
.await
.unwrap()
.status();
assert_eq!(status, 404);
}
Sourcepub async fn register(&self, mock: Mock)
pub async fn register(&self, mock: Mock)
Register a Mock
on an instance of MockServer
.
The Mock
will remain active until MockServer
is shut down. If you want to control or limit how
long your Mock
stays active, check out MockServer::register_as_scoped
.
Be careful! Mock
s are not effective until they are mount
ed or register
ed on a MockServer
.
register
is an asynchronous method, make sure to .await
it!
§Example:
use wiremock::{MockServer, Mock, ResponseTemplate};
use wiremock::matchers::method;
#[async_std::main]
async fn main() {
// Arrange
let mock_server = MockServer::start().await;
let response = ResponseTemplate::new(200);
let mock = Mock::given(method("GET")).respond_with(response.clone());
// Registering the mock with the mock server - it's now effective!
mock_server.register(mock).await;
// We won't register this mock instead.
let unregistered_mock = Mock::given(method("GET")).respond_with(response);
// Act
let status = surf::get(&mock_server.uri())
.await
.unwrap()
.status();
assert_eq!(status, 200);
// This would have matched `unregistered_mock`, but we haven't registered it!
// Hence it returns a 404, the default response when no mocks matched on the mock server.
let status = surf::post(&mock_server.uri())
.await
.unwrap()
.status();
assert_eq!(status, 404);
}
Sourcepub async fn register_as_scoped(&self, mock: Mock) -> MockGuard
pub async fn register_as_scoped(&self, mock: Mock) -> MockGuard
Register a scoped Mock
on an instance of MockServer
.
When using register
, your Mock
s will be active until the MockServer
is shut down.
When using register_as_scoped
, your Mock
s will be active as long as the returned MockGuard
is not dropped.
When the returned MockGuard
is dropped, MockServer
will verify that the expectations set on the scoped Mock
were
verified - if not, it will panic.
register_as_scoped
is the ideal solution when you need a Mock
within a test helper
but you do not want it to linger around after the end of the function execution.
§Limitations
When expectations of a scoped Mock
are not verified, it will trigger a panic - just like a normal Mock
.
Due to limitations in Rust’s Drop
trait,
the panic message will not include the filename and the line location
where the corresponding MockGuard
was dropped - it will point into wiremock
’s source code.
This can be an issue when you are using more than one scoped Mock
in a single test - which of them panicked?
To improve your debugging experience it is strongly recommended to use Mock::named
to assign a unique
identifier to your scoped Mock
s, which will in turn be referenced in the panic message if their expectations are
not met.
§Example:
- The behaviour of the scoped mock is invisible outside of
my_test_helper
.
use wiremock::{MockServer, Mock, ResponseTemplate};
use wiremock::matchers::method;
async fn my_test_helper(mock_server: &MockServer) {
let mock = Mock::given(method("GET"))
.respond_with(ResponseTemplate::new(200))
.expect(1)
.named("my_test_helper GET /");
let mock_guard = mock_server.register_as_scoped(mock).await;
surf::get(&mock_server.uri())
.await
.unwrap();
// `mock_guard` is dropped, expectations are verified!
}
#[async_std::main]
async fn main() {
// Arrange
let mock_server = MockServer::start().await;
my_test_helper(&mock_server).await;
// Act
// This would have returned 200 if the `Mock` in
// `my_test_helper` had not been scoped.
let status = surf::get(&mock_server.uri())
.await
.unwrap()
.status();
assert_eq!(status, 404);
}
- The expectations for the scoped mock are not verified, it panics at the end of
my_test_helper
.
use wiremock::{MockServer, Mock, ResponseTemplate};
use wiremock::matchers::method;
async fn my_test_helper(mock_server: &MockServer) {
let mock = Mock::given(method("GET"))
.respond_with(ResponseTemplate::new(200))
.expect(1)
.named("my_test_helper GET /");
let mock_guard = mock_server.register_as_scoped(mock).await;
// `mock_guard` is dropped, expectations are NOT verified!
// Panic!
}
#[async_std::main]
async fn main() {
// Arrange
let mock_server = MockServer::start().await;
my_test_helper(&mock_server).await;
// Act
let status = surf::get(&mock_server.uri())
.await
.unwrap()
.status();
assert_eq!(status, 404);
}
Sourcepub async fn reset(&self)
pub async fn reset(&self)
Drop all mounted Mock
s from an instance of MockServer
.
It also deletes all recorded requests.
§Example
use wiremock::{MockServer, Mock, ResponseTemplate};
use wiremock::matchers::method;
#[async_std::main]
async fn main() {
// Arrange
let mock_server = MockServer::start().await;
let response = ResponseTemplate::new(200);
Mock::given(method("GET")).respond_with(response).mount(&mock_server).await;
// Act
let status = surf::get(&mock_server.uri())
.await
.unwrap()
.status();
assert_eq!(status, 200);
// Reset the server
mock_server.reset().await;
// This would have matched our mock, but we have dropped it resetting the server!
let status = surf::post(&mock_server.uri())
.await
.unwrap()
.status();
assert_eq!(status, 404);
}
§Example (Recorded requests are reset)
use wiremock::{MockServer, Mock, ResponseTemplate};
use wiremock::matchers::method;
#[async_std::main]
async fn main() {
// Arrange
let mock_server = MockServer::start().await;
// Act
surf::get(&mock_server.uri()).await.unwrap();
// We have recorded the incoming request
let received_requests = mock_server.received_requests().await.unwrap();
assert!(!received_requests.is_empty());
// Reset the server
mock_server.reset().await;
// All received requests have been forgotten after the call to `.reset`
let received_requests = mock_server.received_requests().await.unwrap();
assert!(received_requests.is_empty())
}
Sourcepub async fn verify(&self)
pub async fn verify(&self)
Verify that all mounted Mock
s on this instance of MockServer
have satisfied
their expectations on their number of invocations. Panics otherwise.
Sourcepub fn uri(&self) -> String
pub fn uri(&self) -> String
Return the base uri of this running instance of MockServer
, e.g. http://127.0.0.1:4372
.
Use this method to compose uris when interacting with this instance of MockServer
via
an HTTP client.
§Example:
use wiremock::MockServer;
#[async_std::main]
async fn main() {
// Arrange - no mocks mounted
let mock_server = MockServer::start().await;
// Act
let uri = format!("{}/health_check", &mock_server.uri());
let status = surf::get(uri).await.unwrap().status();
// Assert - default response
assert_eq!(status, 404);
}
Sourcepub fn address(&self) -> &SocketAddr
pub fn address(&self) -> &SocketAddr
Return the socket address of this running instance of MockServer
, e.g. 127.0.0.1:4372
.
Use this method to interact with the MockServer
using TcpStream
s.
§Example:
use wiremock::MockServer;
use std::net::TcpStream;
#[async_std::main]
async fn main() {
// Act - the server is started
let mock_server = MockServer::start().await;
// Assert - we can connect to it
assert!(TcpStream::connect(mock_server.address()).is_ok());
}
Sourcepub async fn received_requests(&self) -> Option<Vec<Request>>
pub async fn received_requests(&self) -> Option<Vec<Request>>
Return a vector with all the requests received by the MockServer
since it started.
If no request has been served, it returns an empty vector.
If request recording has been disabled using MockServerBuilder::disable_request_recording
,
it returns None
.
§Example:
use wiremock::MockServer;
use http::Method;
#[async_std::main]
async fn main() {
// Arrange
let mock_server = MockServer::start().await;
// Act
surf::get(&mock_server.uri()).await.unwrap();
// Assert
let received_requests = mock_server.received_requests().await.unwrap();
assert_eq!(received_requests.len(), 1);
let received_request = &received_requests[0];
assert_eq!(received_request.method, Method::GET);
assert_eq!(received_request.url.path(), "/");
assert!(received_request.body.is_empty());
}
§Example (No request served):
use wiremock::MockServer;
#[async_std::main]
async fn main() {
// Arrange
let mock_server = MockServer::start().await;
// Assert
let received_requests = mock_server.received_requests().await.unwrap();
assert_eq!(received_requests.len(), 0);
}
§Example (Request recording disabled):
use wiremock::MockServer;
#[async_std::main]
async fn main() {
// Arrange
let mock_server = MockServer::builder().disable_request_recording().start().await;
// Assert
let received_requests = mock_server.received_requests().await;
assert!(received_requests.is_none());
}