带有SQLX测试数据库端点的Rust Rocket



我希望测试应用程序的/signup端点。如果电子邮件已存在,则此终结点将失败。我的测试第一次成功了,但之后就失败了。指示数据库正在保存响应。以下是我的代码:

#[macro_use] extern crate rocket;
use sqlx::mysql::MySqlPool;
use rocket::serde::{json::Json};
use rocket::response::status;
use rocket::http::Status;
use crate::schemas::Signup;
pub mod schemas;
#[cfg(test)] mod tests;

#[post("/signup", format = "application/json", data="<task>")]
async fn signup(pool: &rocket::State<MySqlPool>, task: Json<Signup<'_>>) -> status::Custom<String> {
println!("New user. Username: {}, Password: {}", task.email, task.password);
match sqlx::query("INSERT INTO user(email, username, password) VALUES (?, ?, ?)")
.bind(task.email)
.bind(task.username)
.bind(task.password)
.execute(&**pool)
.await {
Err(_) => status::Custom(Status::BadRequest, "Could not add user to database".to_string()),
Ok(_) => status::Custom(Status::Accepted,"Successfully created a new account.".to_string()),
}
}
#[launch]
async fn rocket() -> _ {
let database_url = "mysql://root:root@localhost:3306/dynamicapi?charset=utf8mb4";
let pool = MySqlPool::connect(database_url)
.await
.expect("Failed to connect to database");
rocket::build()
.mount("/", routes![signup])
.manage::<MySqlPool>(pool)
}
#[cfg(test)]
mod test {
use rocket::http::ContentType;
use rocket::local::asynchronous::Client;
async fn get_client() -> Client {
Client::tracked(super::rocket().await).await
.expect("valid `Rocket`")
}
// #[rocket::async_test]
#[sqlx::test]
async fn signup_post() {
let client = get_client().await;
let response = client.post("/signup")
.header(ContentType::JSON)
.body(r##"{
"email": "j.doe@m.com",
"username": "bigjose400",
"password": "123456"
}"##)
.dispatch().await;
assert_eq!(response.status().code, 202);
}
}

然而,我尝试使用sqlx_test的文档;这似乎不起作用。如何集成每次测试后重置的临时数据库?

更新:我现在明白了,我需要这样调用测试来获得测试数据库:

#[sqlx::test]
async fn signup_post(pool: MySqlPool) {

然而,现在我的问题是让这个测试数据库池进入火箭状态。

目前,我通过使用if cfg!(test)查看程序是否在测试模式下运行来修复此问题。如果是这样的话,我会将database_url更改为测试数据库的数据库,然后调用一个函数从每次测试更改的任何表中删除所有行。

查看此博客文章。诀窍是使用async fn(PoolOptions<DB>, impl ConnectOptions<DB>) -> Ret来获取连接细节,而不是连接本身,并使用这些细节来创建自定义figment并将其传递给新的火箭实例。

最新更新