You need to enable JavaScript to run this app. 如何解决actix-web测试中reqwest response所有权移动引发的E0382报错
优惠活动
大模型
产品
解决方案
定价
更多

如何解决actix-web测试中reqwest response所有权移动引发的E0382报错

你遇到的所有权报错是因为 reqwest::Response 的 json() 方法会直接消费(move)Response实例本身:反序列化需要读取完整的响应流,调用该方法后Response的所有权已经被转移,自然无法再调用status()等方法读取响应元数据。
避免断言顺序依赖可以用以下两种无额外心智负担的方案:


方案1:提前提取响应状态(零额外开销,优先推荐)

status()方法本身是只读引用调用,不会消费Response,你可以先把状态值提前存到变量中,再处理响应体,后续断言不受顺序限制:

let inserted_user = sqlx::query!(
    r#"
    INSERT INTO users (name)
    VALUES ($1)
    RETURNING id
    "#,
    String::from("john"),
)
.fetch_one(&app.db_pool)
.await
.unwrap();

let response = client
    .get(&format!("{}/", &app.address))
    .send()
    .await?;

// 提前提取状态,不消费response
let resp_status = response.status();
let users: Vec<User> = response.json().await?;

// 断言顺序完全自由
assert!(resp_status.is_success());
assert_eq!(inserted_user.id, users[0].id);

方案2:提前读取完整响应体,按需使用(适合需要保留原始响应的场景)

如果你需要同时访问响应元数据、原始响应内容、甚至克隆响应内容,可以先把响应体读取为Bytes类型(该类型支持低成本克隆),再手动做反序列化:

let response = client
    .get(&format!("{}/", &app.address))
    .send()
    .await?;

// 读取完整响应体为Bytes,仅消费响应流,不影响Response的元数据访问
let body_bytes = response.bytes().await?;
// 手动反序列化
let users: Vec<User> = serde_json::from_slice(&body_bytes)?;

// 断言顺序完全自由
assert!(response.status().is_success());
assert_eq!(inserted_user.id, users[0].id);

// 有需要的话可以直接克隆Bytes,开销极低
let cloned_body = body_bytes.clone();

关于Response克隆的说明

reqwest的Response本身没有实现Clone trait,原因是响应体默认是流式传输,不会在内存中缓存全量数据,无法直接做克隆。如果有多次使用响应内容的需求,用方案2先读取为Bytes即可满足克隆需求。

内容的提问来源于stack exchange,提问作者Johann Esburgo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 00:00:04