【问题标题】:Clone reqwest response克隆请求响应
【发布时间】:2021-07-12 07:45:21
【问题描述】:

我目前正在尝试使用 actix-web 和 reqwest 测试 API 端点。

我可以插入一些记录(使用 sqlx),然后发出请求并检查它是否返回了 200 HTTP 状态,并证实返回的数据属于用户创建的 - 端点返回了预期的内容。但是,这样做是“订单相关”,否则我会收到以下错误:

借用移动值:response
移动 rustc(E0382) 后在这里借用的值

这是导致错误的原因:

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?;

let users: Vec<User> = response.json().await?;
assert_eq!(inserted_user.id, users[0].id);
assert!(response.status().is_success());

如果我将response.status() 上的断言顺序与assert_eq! 交换,它就可以工作。但我认为这不是最好的方法,正如它应该明确指出的那样,用 cmets 或进一步的知识表明它以这种特定的方式工作。

如果我无法克隆 reqwest 响应,是否可以避免依赖断言的顺序?或者我如何克隆它?

【问题讨论】:

    标签: rust actix-web reqwest


    【解决方案1】:

    说实话,我认为在您得到回复后,这个断言就更有意义了。为什么您要解析响应,而仅 然后 断言响应甚至还可以?如果一开始响应不正确,那么解析很可能无论如何都会失败,您甚至无法到达断言,不是吗?

    但是如果你真的想在那个时候进行断言,你可以在使用响应之前将response.status() 放入一个临时的:

    let status = respons.status();
    let users: Vec<User> = response.json().await?;
    assert_eq!(inserted_user.id, users[0].id);
    assert!(status.is_success());
    

    【讨论】:

    • 答案有效,谢谢。是的,你是对的,也许状态检查是多余的,但是,严格来说,没有什么能阻止我返回任何其他 HTTP 状态代码,即使我也在返回预期的 JSON 正文,不是吗?这样状态码断言会更有意义吗?
    • 不,没有什么能阻止您返回带有 404 状态代码的 json 正文,但问题是,如果响应不成功,您为什么要尝试解析响应?即使它是有效的 json,一旦断言出现恐慌,你也会将其丢弃。我会使用条件检查状态是否正常,如果是则解析响应,如果不是则返回错误。 (哦,如果答案有效,您可以接受它,以便其他人也能看到)