#mocking #websocket #websocket-server #async #send-message #tokio

ws-mock

受 Wiremock 启发的 WebSocket 模拟服务器,用于测试

4 个版本 (2 个破坏性更新)

0.2.0 2024 年 7 月 28 日
0.1.1 2024 年 5 月 21 日
0.1.0 2024 年 5 月 5 日
0.0.1 2024 年 2 月 19 日

#149 in 测试

Download history 127/week @ 2024-04-29 67/week @ 2024-05-06 8/week @ 2024-05-13 196/week @ 2024-05-20 68/week @ 2024-05-27 44/week @ 2024-06-03 28/week @ 2024-06-10 35/week @ 2024-06-17 39/week @ 2024-06-24 104/week @ 2024-07-01 63/week @ 2024-07-08 107/week @ 2024-07-15 173/week @ 2024-07-22 136/week @ 2024-07-29 105/week @ 2024-08-05 113/week @ 2024-08-12

每月 535 次下载
用于 kraken-async-rs

MIT 许可证

45KB
643

ws-mock

一个 WebSocket 测试的模拟服务器,能够根据接收到的消息进行任意匹配并相应地响应。

badge License: MIT codecov

WS-Mock 允许你设置一个模拟服务器来测试 WebSocket 代码,并根据接收到的数据进行动态响应。

示例:响应心跳消息

使用 JsonExact 匹配器,WsMock 将匹配包含与给定的 JSON 完全相同的消息,并响应字符串 "heartbeat"。

可以在单个 WsMockServer 上挂载多个模拟,调用 server.verify().await 将检查每个模拟的期望是否由传入的消息满足。任何失败将导致 panic,详细说明看到了哪些消息以及期望看到哪些。

模拟需要 .respond_with(...).forward_from_channel(...)expect(...),因为挂载一个不响应、不转发消息或不对任何调用进行预期的模拟将没有任何可识别的效果。如果在没有响应或预期调用数的情况下挂载 WsMock,这将产生 panic。如果需要验证从未接收到某种类型的数据,也可以完全合法地对模拟进行 .expect(0) 调用。

use futures_util::{SinkExt, StreamExt};
use serde_json::json;
use tokio_tungstenite::connect_async;
use tokio_tungstenite::tungstenite::Message;
use ws_mock_test::matchers::JsonExact;
use ws_mock_test::ws_mock_server::{WSMock, WSMockServer};

#[tokio::main]
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, _recv) = stream.split();

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

    server.verify().await;
}

示例:模拟实时流数据

许多WebSocket示例不依赖于通过WebSocket响应请求,而是从服务器流式传输数据,无需客户端输入。测试这一点需要服务器接受消息并将它们发送到客户端。通过以下代码实现:WsMock.forward_from_channel(...) 允许用户发送任意消息,然后服务器将这些消息中继给客户端。

在下面的示例中,测试通过向配置在 [WsMock] 上的通道发送消息来模拟流式传输数据。由于它的唯一用途是转发模拟实时服务器的消息,因此模拟没有 .expect(...).respond_with(...) 调用。

use futures_util::StreamExt;
use std::time::Duration;
use tokio::sync::mpsc;
use tokio_tungstenite::connect_async;
use tokio_tungstenite::tungstenite::Message;
use ws_mock::utils::collect_all_messages;
use ws_mock::ws_mock_server::{WsMock, WsMockServer};

#[tokio::main]
pub async fn main() {
    let server = WsMockServer::start().await;

    let (mpsc_send, mpsc_recv) = mpsc::channel::<String>(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);
}

贡献

请与我们联系或提交一个PR!尤其是如果您有新的通用 Matcher 实现,这将使其他用户受益。

依赖项

~6–13MB
~156K SLoC