ws_mock::ws_mock_server

Struct WsMock

source
pub struct WsMock { /* private fields */ }
Expand description

An individual mock that matches on one or more matchers, and expects a particular number of calls and/or responds with configured data.

Each WsMock can have many Matchers added to it before mounting it to a WsMockServer, and will only respond if all the added matchers match successfully. A mock must either have an expected number of calls, or respond with data before being mounted.

Mocks must be mounted to a WsMockServer to have any effect! Failing to call server.verify().await will also erroneously pass tests, as this is how the server is told to verify that all mocks were called as expected. If you rely only on the response from the server as part of a test and have no .expect(...) call, the call to .verify() can be omitted.

§Example

The below WsMock will match on any incoming data and respond with “Hello World”. In this case, it expects no messages, since we don’t send it any.

use ws_mock::matchers::Any;
use ws_mock::ws_mock_server::{WsMock, WsMockServer};

#[tokio::main]
async fn main() -> () {
    use tokio_tungstenite::tungstenite::Message;
let server = WsMockServer::start().await;

    WsMock::new()
        .matcher(Any::new())
        .respond_with(Message::Text("Hello World".to_string()))
        .expect(0)
        .mount(&server)
        .await;

    server.verify().await;
}

Implementations§

source§

impl WsMock

source

pub fn new() -> WsMock

Examples found in repository?
examples/any_match.rs (line 13)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
pub async fn main() {
    let server = WsMockServer::start().await;

    WsMock::new()
        .matcher(Any::new())
        .respond_with(Message::Text("Hello World".to_string()))
        .expect(1)
        .mount(&server)
        .await;

    let (stream, _resp) = connect_async(server.uri().await)
        .await
        .expect("Connecting failed");

    let (mut send, mut recv) = stream.split();

    send.send(Message::from("some message")).await.unwrap();

    let mut received = Vec::new();

    while let Ok(Some(Ok(message))) = timeout(Duration::from_millis(100), recv.next()).await {
        received.push(message);
    }

    server.verify().await;
    assert_eq!(vec![Message::Text("Hello World".to_string())], received);
}
More examples
Hide additional examples
examples/forwarding_messages.rs (line 15)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
pub async fn main() {
    let server = WsMockServer::start().await;

    let (mpsc_send, mpsc_recv) = mpsc::channel::<Message>(32);

    WsMock::new()
        .forward_from_channel(mpsc_recv)
        .mount(&server)
        .await;

    let (stream, _resp) = connect_async(server.uri().await)
        .await
        .expect("Connecting failed");

    let (_send, ws_recv) = stream.split();

    mpsc_send
        .send(Message::Text("message-1".to_string()))
        .await
        .unwrap();
    mpsc_send
        .send(Message::Text("message-2".to_string()))
        .await
        .unwrap();

    let received = collect_all_messages(ws_recv, Duration::from_millis(250)).await;

    server.verify().await;
    assert_eq!(
        vec![
            Message::Text("message-1".to_string()),
            Message::Text("message-2".to_string())
        ],
        received
    );
}
examples/json_match.rs (line 17)
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
pub async fn main() {
    let expected_json = json!({"message": "heartbeat"});
    let json_msg = serde_json::to_string(&expected_json).expect("Failed to serialize message");

    let server = WsMockServer::start().await;

    WsMock::new()
        .matcher(JsonExact::new(expected_json))
        .respond_with(Message::Text("heartbeat".to_string()))
        .expect(1)
        .mount(&server)
        .await;

    let (stream, _resp) = connect_async(server.uri().await)
        .await
        .expect("Connecting failed");

    let (mut send, mut recv) = stream.split();

    send.send(Message::from(json_msg)).await.unwrap();

    let mut received = Vec::new();

    while let Ok(Some(Ok(message))) = timeout(Duration::from_millis(100), recv.next()).await {
        received.push(message.to_string());
    }

    server.verify().await;
    assert_eq!(vec!["heartbeat"], received);

    server.verify().await;
}
source

pub fn matcher<T: Matcher + 'static>(self, matcher: T) -> Self

Add a Matcher to this WsMock instance.

All attached matchers must match for this mock to respond with any data or record a call.

Examples found in repository?
examples/any_match.rs (line 14)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
pub async fn main() {
    let server = WsMockServer::start().await;

    WsMock::new()
        .matcher(Any::new())
        .respond_with(Message::Text("Hello World".to_string()))
        .expect(1)
        .mount(&server)
        .await;

    let (stream, _resp) = connect_async(server.uri().await)
        .await
        .expect("Connecting failed");

    let (mut send, mut recv) = stream.split();

    send.send(Message::from("some message")).await.unwrap();

    let mut received = Vec::new();

    while let Ok(Some(Ok(message))) = timeout(Duration::from_millis(100), recv.next()).await {
        received.push(message);
    }

    server.verify().await;
    assert_eq!(vec![Message::Text("Hello World".to_string())], received);
}
More examples
Hide additional examples
examples/json_match.rs (line 18)
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
pub async fn main() {
    let expected_json = json!({"message": "heartbeat"});
    let json_msg = serde_json::to_string(&expected_json).expect("Failed to serialize message");

    let server = WsMockServer::start().await;

    WsMock::new()
        .matcher(JsonExact::new(expected_json))
        .respond_with(Message::Text("heartbeat".to_string()))
        .expect(1)
        .mount(&server)
        .await;

    let (stream, _resp) = connect_async(server.uri().await)
        .await
        .expect("Connecting failed");

    let (mut send, mut recv) = stream.split();

    send.send(Message::from(json_msg)).await.unwrap();

    let mut received = Vec::new();

    while let Ok(Some(Ok(message))) = timeout(Duration::from_millis(100), recv.next()).await {
        received.push(message.to_string());
    }

    server.verify().await;
    assert_eq!(vec!["heartbeat"], received);

    server.verify().await;
}
source

pub fn respond_with(self, data: Message) -> Self

Respond with a message, if/when all attached matchers match on a message.

Examples found in repository?
examples/any_match.rs (line 15)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
pub async fn main() {
    let server = WsMockServer::start().await;

    WsMock::new()
        .matcher(Any::new())
        .respond_with(Message::Text("Hello World".to_string()))
        .expect(1)
        .mount(&server)
        .await;

    let (stream, _resp) = connect_async(server.uri().await)
        .await
        .expect("Connecting failed");

    let (mut send, mut recv) = stream.split();

    send.send(Message::from("some message")).await.unwrap();

    let mut received = Vec::new();

    while let Ok(Some(Ok(message))) = timeout(Duration::from_millis(100), recv.next()).await {
        received.push(message);
    }

    server.verify().await;
    assert_eq!(vec![Message::Text("Hello World".to_string())], received);
}
More examples
Hide additional examples
examples/json_match.rs (line 19)
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
pub async fn main() {
    let expected_json = json!({"message": "heartbeat"});
    let json_msg = serde_json::to_string(&expected_json).expect("Failed to serialize message");

    let server = WsMockServer::start().await;

    WsMock::new()
        .matcher(JsonExact::new(expected_json))
        .respond_with(Message::Text("heartbeat".to_string()))
        .expect(1)
        .mount(&server)
        .await;

    let (stream, _resp) = connect_async(server.uri().await)
        .await
        .expect("Connecting failed");

    let (mut send, mut recv) = stream.split();

    send.send(Message::from(json_msg)).await.unwrap();

    let mut received = Vec::new();

    while let Ok(Some(Ok(message))) = timeout(Duration::from_millis(100), recv.next()).await {
        received.push(message.to_string());
    }

    server.verify().await;
    assert_eq!(vec!["heartbeat"], received);

    server.verify().await;
}
source

pub fn forward_from_channel(self, receiver: MpscReceiver<Message>) -> Self

Forward any messages from the provided mpsc Receiver.

This provides the ability for “live” streams common in websockets, since you can provide any messages directly to control the stream of messages.

Forwarding can be used in conjunction with .respond_with(...) and/or .expect(...), but neither is required to use forwarding. Calling .matcher(...) has no effect on what values will be forwarded from the provided channel.

§Example: Passing Messages Through

Tests may mock the data sent by the server, and need to assert they’re parsed correctly by a client. Since this doesn’t require sending data to the server and receiving a response, another mechanism aside from .respond_with(...) is needed. forward_from_channel fills this need.

Here, a channel is added to a WsMock that has no expectations or response data, and used to send two messages through to the client. Any subsequent client behavior canbe tested based on the received data.

use ws_mock::matchers::Any;
use ws_mock::utils::collect_all_messages;
use ws_mock::ws_mock_server::{WsMock, WsMockServer};
use futures_util::StreamExt;
use tokio::sync::mpsc;

#[tokio::main]
pub async fn main() {
    use std::time::Duration;
    use futures_util::SinkExt;
    use tokio_tungstenite::connect_async;
    use tokio_tungstenite::tungstenite::Message;
    let server = WsMockServer::start().await;

    let (mpsc_send, mpsc_recv) = mpsc::channel::<Message>(32);

    WsMock::new()
        .forward_from_channel(mpsc_recv)
        .mount(&server)
        .await;

    let (stream, _resp) = connect_async(server.uri().await)
        .await
        .expect("Connecting failed");

    let (_send, ws_recv) = stream.split();

    mpsc_send.send(Message::Text("message-1".to_string())).await.unwrap();
    mpsc_send.send(Message::Text("message-2".into())).await.unwrap();

    let received = collect_all_messages(ws_recv, Duration::from_millis(250)).await;

    server.verify().await;
    assert_eq!(vec![Message::Text("message-1".to_string()), Message::Text("message-2".to_string())], received);
}
Examples found in repository?
examples/forwarding_messages.rs (line 16)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
pub async fn main() {
    let server = WsMockServer::start().await;

    let (mpsc_send, mpsc_recv) = mpsc::channel::<Message>(32);

    WsMock::new()
        .forward_from_channel(mpsc_recv)
        .mount(&server)
        .await;

    let (stream, _resp) = connect_async(server.uri().await)
        .await
        .expect("Connecting failed");

    let (_send, ws_recv) = stream.split();

    mpsc_send
        .send(Message::Text("message-1".to_string()))
        .await
        .unwrap();
    mpsc_send
        .send(Message::Text("message-2".to_string()))
        .await
        .unwrap();

    let received = collect_all_messages(ws_recv, Duration::from_millis(250)).await;

    server.verify().await;
    assert_eq!(
        vec![
            Message::Text("message-1".to_string()),
            Message::Text("message-2".to_string())
        ],
        received
    );
}
source

pub fn expect(self, n: usize) -> Self

Expect for this mock to be matched against n times.

Calling server.verify().await will panic if this mock did not match accordingly.

Examples found in repository?
examples/any_match.rs (line 16)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
pub async fn main() {
    let server = WsMockServer::start().await;

    WsMock::new()
        .matcher(Any::new())
        .respond_with(Message::Text("Hello World".to_string()))
        .expect(1)
        .mount(&server)
        .await;

    let (stream, _resp) = connect_async(server.uri().await)
        .await
        .expect("Connecting failed");

    let (mut send, mut recv) = stream.split();

    send.send(Message::from("some message")).await.unwrap();

    let mut received = Vec::new();

    while let Ok(Some(Ok(message))) = timeout(Duration::from_millis(100), recv.next()).await {
        received.push(message);
    }

    server.verify().await;
    assert_eq!(vec![Message::Text("Hello World".to_string())], received);
}
More examples
Hide additional examples
examples/json_match.rs (line 20)
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
pub async fn main() {
    let expected_json = json!({"message": "heartbeat"});
    let json_msg = serde_json::to_string(&expected_json).expect("Failed to serialize message");

    let server = WsMockServer::start().await;

    WsMock::new()
        .matcher(JsonExact::new(expected_json))
        .respond_with(Message::Text("heartbeat".to_string()))
        .expect(1)
        .mount(&server)
        .await;

    let (stream, _resp) = connect_async(server.uri().await)
        .await
        .expect("Connecting failed");

    let (mut send, mut recv) = stream.split();

    send.send(Message::from(json_msg)).await.unwrap();

    let mut received = Vec::new();

    while let Ok(Some(Ok(message))) = timeout(Duration::from_millis(100), recv.next()).await {
        received.push(message.to_string());
    }

    server.verify().await;
    assert_eq!(vec!["heartbeat"], received);

    server.verify().await;
}
source

pub async fn mount(self, server: &WsMockServer)

Mount this mock to an instance of WsMockServer

Mounting a mock without having called .respond_with(...), .forward_from_channel(...), or .expect(...) will panic, since the mock by definition can have no effects.

Examples found in repository?
examples/any_match.rs (line 17)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
pub async fn main() {
    let server = WsMockServer::start().await;

    WsMock::new()
        .matcher(Any::new())
        .respond_with(Message::Text("Hello World".to_string()))
        .expect(1)
        .mount(&server)
        .await;

    let (stream, _resp) = connect_async(server.uri().await)
        .await
        .expect("Connecting failed");

    let (mut send, mut recv) = stream.split();

    send.send(Message::from("some message")).await.unwrap();

    let mut received = Vec::new();

    while let Ok(Some(Ok(message))) = timeout(Duration::from_millis(100), recv.next()).await {
        received.push(message);
    }

    server.verify().await;
    assert_eq!(vec![Message::Text("Hello World".to_string())], received);
}
More examples
Hide additional examples
examples/forwarding_messages.rs (line 17)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
pub async fn main() {
    let server = WsMockServer::start().await;

    let (mpsc_send, mpsc_recv) = mpsc::channel::<Message>(32);

    WsMock::new()
        .forward_from_channel(mpsc_recv)
        .mount(&server)
        .await;

    let (stream, _resp) = connect_async(server.uri().await)
        .await
        .expect("Connecting failed");

    let (_send, ws_recv) = stream.split();

    mpsc_send
        .send(Message::Text("message-1".to_string()))
        .await
        .unwrap();
    mpsc_send
        .send(Message::Text("message-2".to_string()))
        .await
        .unwrap();

    let received = collect_all_messages(ws_recv, Duration::from_millis(250)).await;

    server.verify().await;
    assert_eq!(
        vec![
            Message::Text("message-1".to_string()),
            Message::Text("message-2".to_string())
        ],
        received
    );
}
examples/json_match.rs (line 21)
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
pub async fn main() {
    let expected_json = json!({"message": "heartbeat"});
    let json_msg = serde_json::to_string(&expected_json).expect("Failed to serialize message");

    let server = WsMockServer::start().await;

    WsMock::new()
        .matcher(JsonExact::new(expected_json))
        .respond_with(Message::Text("heartbeat".to_string()))
        .expect(1)
        .mount(&server)
        .await;

    let (stream, _resp) = connect_async(server.uri().await)
        .await
        .expect("Connecting failed");

    let (mut send, mut recv) = stream.split();

    send.send(Message::from(json_msg)).await.unwrap();

    let mut received = Vec::new();

    while let Ok(Some(Ok(message))) = timeout(Duration::from_millis(100), recv.next()).await {
        received.push(message.to_string());
    }

    server.verify().await;
    assert_eq!(vec!["heartbeat"], received);

    server.verify().await;
}

Trait Implementations§

source§

impl Debug for WsMock

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for WsMock

source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl Freeze for WsMock

§

impl !RefUnwindSafe for WsMock

§

impl Send for WsMock

§

impl Sync for WsMock

§

impl Unpin for WsMock

§

impl !UnwindSafe for WsMock

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

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

fn in_current_span(self) -> Instrumented<Self>

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

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

source§

fn vzip(self) -> V

source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more