如何解决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
相关产品推荐
相关产品推荐

