首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >无法在Actix集成测试中将app_data内容传递给处理程序方法

无法在Actix集成测试中将app_data内容传递给处理程序方法
EN

Stack Overflow用户
提问于 2022-08-11 11:15:44
回答 1查看 117关注 0票数 0

我想在我的处理程序函数中从HttpRequest中提取我的HttpRequest结构。当我通过我的主要应用程序实例调用该处理程序时,它可以工作,但在集成测试中不能工作。

处理程序功能:

代码语言:javascript
运行
复制
pub async fn handle(req: HttpRequest, user: Json<NewUser>) -> Result<HttpResponse, ShopError> {
    let state = req.app_data::<Data<AppState>>().expect("app_data is empty!");
    Ok(HttpResponse::Ok().finish())
}

main.rs:

代码语言:javascript
运行
复制
#[actix_web::main]
pub async fn main() -> std::io::Result<()> {
    dotenv().ok();
    let chat_server = Lobby::default().start();
    let state = AppState {
            static_data: String::from("my_data")
        };
    HttpServer::new(move || {
        App::new()
            .app_data(Data::new(state.clone()))
            .service(web::scope("/").configure(routes::router))
            .app_data(Data::new(chat_server.clone()))
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

测试:

代码语言:javascript
运行
复制
#[actix_web::test]
    async fn sanity_test() {
        let app = test::init_service(App::new().route("/", web::post().to(handle))).await;
        let user = NewUser {
            username: String::from("legit_user"),
            password: String::from("123"),
        };
        let state = AppState {
            static_data: String::from("my_data")
        };
        let req = test::TestRequest::post()
            .app_data(Data::new(state))
            .set_json(&user)
            .uri("/")
            .to_request();
        let resp = test::call_service(&app, req).await;
        assert!(resp.status().is_success());
    }

测试输出:

代码语言:javascript
运行
复制
running 1 test
thread 'routes::login::tests::sanity_test' panicked at 'app_data is empty!', src/routes/login.rs:35:50

出于某种原因,它总是None。我尝试过使用Data<AppState>提取器,但是整个处理程序甚至不会被调用,同样,只在测试时调用,否则一切都正常。

Cargo.toml:

代码语言:javascript
运行
复制
[dependencies]
diesel = { version = "1.4.4", features = ["postgres", "r2d2", "chrono"] }
diesel_migrations = "1.4.0"
chrono = { version = "0.4.19", features = ["serde"] }
dotenv = "0.15.0"
actix = "0.13.0"
actix-web = "4.1.0"
actix-web-actors = "4.1.0"
bcrypt = "0.13.0"
uuid = { version = "1.1.2", features = ["serde", "v4"] }
serde_json = "1.0.82"
serde = { version = "1.0.139", features = ["derive"] }
validator = { version = "0.16.0", features = ["derive"] }
derive_more = "0.99.17"
r2d2 = "0.8.10"
lazy_static = "1.4.0"
jsonwebtoken = "8.1.1"

我知道app_data is always None in request handler线程,它不能解决我的问题,因为对我来说,除了测试之外,一切都能工作。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-15 10:50:51

根据我在集成测试中所看到的,app_data不是为传递给test::init_service的应用实例配置的,这就是处理程序恐慌的原因。当应用程序配置了app_data,就像您在main中所做的那样,app_data就可以用于处理程序了。

通过下面的代码,处理程序可以在集成测试中访问AppData。与原始帖子的主要区别在于,集成测试中的应用程序配置的是app_data,而不是请求。

代码语言:javascript
运行
复制
use actix_web::{
    HttpServer, 
    HttpRequest, 
    HttpResponse, 
    App,
    web::{Data, Json},
    post,
};

use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
pub struct NewUser{
    username: String,
    password: String,
}

#[derive(Clone)]
struct AppState{
    static_data: String,
}

#[post("/")]
pub async fn handle(
    req: HttpRequest, 
    _user: Json<NewUser>
) -> HttpResponse {
    let state = req
        .app_data::<Data<AppState>>()
        .expect("app_data is empty!");
    println!("Static data: {}", state.static_data);
    HttpResponse::Ok().finish()
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let state = AppState{
        static_data: "Sparta".to_string(),
    };
    HttpServer::new(move || {
        App::new()
            .app_data(Data::new(state.clone()))
            .service(handle)
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

#[cfg(test)]
mod tests {
    use super::*;
    use actix_web::{
        test,
    };

    #[actix_web::test]
    async fn itest() {
        // Set up app with test::init_service
        let state = AppState {
            static_data: "Sparta".to_string(),
        };

        let app = test::init_service(
            App::new()
                .app_data(Data::new(state.clone()))
                .service(handle)
        ).await;

        // Prepare request
        let sample_user = NewUser{
            username: "legit_user".to_string(),
            password: "nosecret123".to_string(),
        };

        let req = test::TestRequest::post()
            
            .set_json(&sample_user)
            .uri("/")
            .to_request();
        
        // Send request and await response
        let resp = test::call_service(&app, req).await;
        assert!(resp.status().is_success())

    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73319749

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档