You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rocket框架的异步测试中连接WebSocket路由?

如何在Rocket框架的异步测试中连接WebSocket路由?

这个问题我之前也碰到过,Rocket的本地测试客户端确实没绑定真实端口,没法直接用Tungstenite这类外部客户端连接,但其实我们完全可以在进程内完成WebSocket的测试,不用依赖外部网络。下面给你具体的解决方法和代码示例:

首先,Rocket的异步本地客户端支持处理WebSocket的升级请求,我们只需要在测试中添加标准的WebSocket握手头,然后通过.upgrade()方法获取到WebSocket会话,就能直接和你的路由进行消息交互了。

完整测试代码示例

#[cfg(test)]
mod tests {
    use rocket::local::asynchronous::Client;
    use rocket_ws::{WebSocket, Message};
    use super::*;

    #[rocket::async_test]
    async fn test_websocket_echo() {
        // 1. 构建并启动Rocket测试实例
        let rocket = rocket::build()
            .mount("/", routes![super::ws_route]);
        let client = Client::tracked(rocket).await
            .expect("Failed to initialize test client");

        // 2. 发起带有WebSocket握手头的升级请求
        let mut ws_session = client.get("/some_route")
            .header("Connection", "Upgrade")
            .header("Upgrade", "websocket")
            .header("Sec-WebSocket-Version", "13")
            .header("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==") // 标准测试用密钥
            .upgrade()
            .await
            .expect("Failed to upgrade to WebSocket connection");

        // 3. 测试消息发送与接收(这里假设你的路由是回声服务)
        let test_msg = "Hello from WebSocket test!";
        ws_session.send(Message::Text(test_msg.into())).await
            .expect("Failed to send test message");

        // 接收服务器返回的消息
        if let Some(received) = ws_session.recv().await {
            match received {
                Ok(Message::Text(echoed)) => assert_eq!(echoed, format!("Echo: {}", test_msg)),
                Ok(_) => panic!("Expected text message, got other type"),
                Err(e) => panic!("Error receiving message: {}", e),
            }
        } else {
            panic!("WebSocket connection closed unexpectedly");
        }

        // 4. 主动关闭连接
        ws_session.close().await.expect("Failed to close WebSocket");
    }
}

关键细节说明

  • 握手头的必要性:这些头是WebSocket协议要求的标准升级头,缺少任何一个都会导致服务器拒绝升级请求。其中Sec-WebSocket-Key只是用于验证握手的随机字符串,测试里用标准示例值即可,服务器会自动处理验证。
  • .upgrade()方法:和普通请求用.dispatch()不同,.upgrade()会完成WebSocket的握手流程,直接返回可用的WebSocket会话实例,让你可以和路由中的WebSocket句柄直接交互。
  • 异步测试宏:一定要用#[rocket::async_test]标记测试函数,它会自动处理Rocket异步测试所需的运行时环境。

对应路由示例(供参考)

如果你的WebSocket路由是回声服务,大概是这样的:

use rocket_ws::{WebSocket, Channel, Message};

#[get("/some_route")]
async fn ws_route(mut ws: WebSocket) -> Channel<'static> {
    while let Some(msg) = ws.recv().await {
        match msg {
            Ok(Message::Text(text)) => {
                let _ = ws.send(Message::Text(format!("Echo: {}", text))).await;
            }
            Ok(_) => continue,
            Err(_) => break,
        }
    }
    ws.channel()
}

这种方式完全在进程内完成测试,没有网络开销,速度很快,而且能完整覆盖WebSocket路由的业务逻辑。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 11:59:51