Struct wiremock::MockServer[][src]

pub struct MockServer(_);
Expand description

An HTTP web-server running in the background to behave as one of your dependencies using Mocks 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, MockServers shouldn’t be shared between tests. Instead, MockServers 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 Mocks as your scenario requires on a MockServer.

Implementations

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.

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);
}

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! Mocks are not effective until they are mounted or registered 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);
}

Register a scoped Mock on an instance of MockServer.

When using register, your Mocks will be active until the MockServer is shut down.
When using register_as_scoped, your Mocks 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 Mocks, 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);
}

Drop all mounted Mocks 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())
}

Verify that all mounted Mocks on this instance of MockServer have satisfied their expectations on their number of invocations. Panics otherwise.

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);
}

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 TcpStreams.

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());
}

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_types::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());
}

Trait Implementations

Executes the destructor for this type. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more

Instruments this type with the current Span, returning an Instrumented wrapper. Read more

Performs the conversion.

Should always be Self

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.