在Rust中的Actix Web测试请求中获取响应正文

问题描述

我正在使用rust和actix构建Web api服务。

我想测试一条路线,并检查接收到的响应主体是否符合我的期望。 但是我正在努力将接收到的主体(ResponseBody)转换为Json / Bson。被调用的路由实际上返回application / json。

感谢您的帮助。

 let mut app = test::init_service(App::new()
            .data(AppState { database: db.clone() })
            .route("/recipes/{id}",web::post().to(add_one_recipe))).await;

        let payload = create_one_recipe().as_document().unwrap().clone();

        let req = test::TestRequest::post()
            .set_json(&payload).uri("/recipes/new").to_request();

        let mut resp = test::call_service(&mut app,req).await;
        let body: ResponseBody<Body> = resp.take_body(); // Here i want the body as Binary,String or Json/Bson what the response actually is (application/json)

解决方法

actix/examples 存储库通过定义新特征并在 ResponseBody<Body> 类型上实现它以在可能的情况下将其内容作为 &str 返回来实现这一点:

trait BodyTest {
    fn as_str(&self) -> &str;
}

impl BodyTest for ResponseBody<Body> {
    fn as_str(&self) -> &str {
        match self {
            ResponseBody::Body(ref b) => match b {
                Body::Bytes(ref by) => std::str::from_utf8(&by).unwrap(),_ => panic!(),},ResponseBody::Other(ref b) => match b {
                Body::Bytes(ref by) => std::str::from_utf8(&by).unwrap(),}
    }
}

之后你可以简单地做:

assert_eq!(resp.response().body().as_str(),"Your name is John");

这些摘录的完整代码参考来自:https://github.com/actix/examples/blob/master/forms/form/src/main.rs

,

看看Body和ResponseBody,它看起来像这样:

use actix_web::{web,App,HttpResponse,HttpServer,Responder};
use serde::{Deserialize,Serialize};

#[derive(Serialize,Deserialize)]
struct Greet {
    name: String,}

async fn greet() -> impl Responder {
    let body = serde_json::to_string(&Greet {
        name: "Test".to_owned(),})
    .unwrap();
    HttpResponse::Ok()
        .content_type("application/json")
        .body(body)
}

#[actix_rt::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().route("/",web::get().to(greet)))
        .bind("127.0.0.1:8000")?
        .run()
        .await
}

#[cfg(test)]
mod tests {
    use super::*;
    use actix_web::{body::Body,test,web,App};
    use serde_json::json;

    #[actix_rt::test]
    async fn test_greet_get() {
        let mut app = test::init_service(App::new().route("/",web::get().to(greet))).await;
        let req = test::TestRequest::with_header("content-type","application/json").to_request();
        let mut resp = test::call_service(&mut app,req).await;
        let body = resp.take_body();
        let body = body.as_ref().unwrap();
        assert!(resp.status().is_success());
        assert_eq!(
            &Body::from(json!({"name":"Test"})),// or serde.....
            body
        );
    }
}
running 1 test
test tests::test_greet_get ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
,
#[actix_rt::test]
pub async fn test_index() {
    let mut app = test::init_service(App::new().service(ping)).await;
    let req = test::TestRequest::get().uri("/ping").to_request();
    let result = test::read_response(&mut app,req).await;
    assert_eq!(result,Bytes::from_static(b"PONG"));
}

请参阅doc

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...