Add integration test for rocket (#3785)
Co-authored-by: Tobie Morgan Hitchcock <tobie@surrealdb.com>
This commit is contained in:
parent
829fb0baf9
commit
3dc00c8229
5 changed files with 154 additions and 13 deletions
|
@ -7,7 +7,7 @@ publish = false
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
rocket = { version = "0.5.0-rc.2", features = ["json"] }
|
||||
surrealdb = { path = "../.." ,features = ["kv-mem"]}
|
||||
rocket = { version = "0.5.0", features = ["json"] }
|
||||
surrealdb = { path = "../..", features = ["kv-mem"]}
|
||||
serde_json = "1.0"
|
||||
thiserror = "1.0.50"
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
mod error;
|
||||
pub mod person;
|
||||
|
||||
use rocket::serde::{Deserialize, Serialize};
|
||||
use rocket::{routes, Build};
|
||||
use std::env;
|
||||
use surrealdb::engine::any;
|
||||
|
@ -10,12 +9,6 @@ use surrealdb::opt::auth::Root;
|
|||
use surrealdb::opt::Config;
|
||||
use surrealdb::Surreal;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct Person {
|
||||
name: String,
|
||||
}
|
||||
|
||||
pub type Db = Surreal<Any>;
|
||||
|
||||
pub async fn create_db_connection() -> Result<Db, Box<dyn std::error::Error>> {
|
||||
|
@ -36,7 +29,14 @@ pub fn router(db_conn: Surreal<Any>) -> rocket::Rocket<Build> {
|
|||
rocket::build()
|
||||
.mount(
|
||||
"/",
|
||||
routes![person::create, person::read, person::update, person::delete, person::list],
|
||||
routes![
|
||||
person::create,
|
||||
person::read,
|
||||
person::update,
|
||||
person::delete,
|
||||
person::list,
|
||||
person::delete_all
|
||||
],
|
||||
)
|
||||
.manage(db_conn)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ extern crate rocket;
|
|||
use rocket_example::{create_db_connection, router};
|
||||
|
||||
#[launch]
|
||||
async fn rocket() -> _ {
|
||||
pub async fn rocket() -> _ {
|
||||
let db_conn = create_db_connection().await.unwrap();
|
||||
router(db_conn)
|
||||
}
|
||||
|
|
|
@ -5,10 +5,11 @@ use rocket::serde::{json::Json, Deserialize, Serialize};
|
|||
use rocket::State;
|
||||
use rocket::{delete, get, post, put};
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct Person {
|
||||
name: String,
|
||||
// pub id: Option<i32>,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
const PERSON: &str = "person";
|
||||
|
@ -35,6 +36,16 @@ pub async fn delete(db: &State<Db>, id: String) -> Result<Json<Option<Person>>,
|
|||
.map(Json)
|
||||
}
|
||||
|
||||
//delete_all
|
||||
// curl -X DELETE http://localhost:8080/persons
|
||||
#[delete("/persons")]
|
||||
pub async fn delete_all(db: &State<Db>) -> Result<Json<Vec<Person>>, Custom<String>> {
|
||||
db.delete(PERSON)
|
||||
.await
|
||||
.map_err(|e| Custom(Status::InternalServerError, e.to_string()))
|
||||
.map(Json)
|
||||
}
|
||||
|
||||
// curl -X GET http://localhost:8080/person/1
|
||||
#[get("/person/<id>")]
|
||||
pub async fn read(db: &State<Db>, id: String) -> Result<Json<Option<Person>>, Custom<String>> {
|
||||
|
|
130
lib/examples/rocket/tests/integration_test.rs
Normal file
130
lib/examples/rocket/tests/integration_test.rs
Normal file
|
@ -0,0 +1,130 @@
|
|||
use rocket::http::{ContentType, Status};
|
||||
use rocket::local::asynchronous::Client;
|
||||
use rocket_example::create_db_connection;
|
||||
use rocket_example::person::Person;
|
||||
use rocket_example::router;
|
||||
|
||||
macro_rules! run_test {
|
||||
(|$client:ident| $block:expr) => {{
|
||||
rocket::async_test(async move {
|
||||
let db_conn = create_db_connection().await.unwrap();
|
||||
let $client = Client::tracked(router(db_conn)).await.unwrap();
|
||||
$block
|
||||
});
|
||||
}};
|
||||
}
|
||||
|
||||
async fn query_persons(client: &Client) -> Vec<Person> {
|
||||
let response = client.get("/people").dispatch().await;
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
let body = response.into_string().await.unwrap();
|
||||
serde_json::from_str(&body).unwrap()
|
||||
}
|
||||
|
||||
async fn read_person(client: &Client, id: i32) -> Person {
|
||||
let response = client.get(format!("/person/{}", id)).dispatch().await;
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
let body = response.into_string().await.unwrap();
|
||||
serde_json::from_str(&body).unwrap()
|
||||
}
|
||||
|
||||
async fn update_person(client: &Client, id: i32, new_name: &str) {
|
||||
let response = client
|
||||
.put(format!("/person/{}", id))
|
||||
.header(ContentType::JSON)
|
||||
.body(format!(r#"{{"name":"{}"}}"#, new_name))
|
||||
.dispatch()
|
||||
.await;
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
}
|
||||
|
||||
async fn delete_person(client: &Client, id: i32) {
|
||||
let response = client.delete(format!("/person/{}", id)).dispatch().await;
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
}
|
||||
|
||||
async fn delete_all_persons(client: &Client) {
|
||||
let response = client.delete("/persons").dispatch().await;
|
||||
assert_eq!(response.status(), Status::Ok);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_person() {
|
||||
run_test!(|client| {
|
||||
// Insert a person to ensure the database is not empty.
|
||||
let john_id = 1;
|
||||
client
|
||||
.post(format!("/person/{}", john_id))
|
||||
.header(ContentType::JSON)
|
||||
.body(r#"{"name":"John Doe"}"#)
|
||||
.dispatch()
|
||||
.await;
|
||||
|
||||
// Read the inserted person's data.
|
||||
let person_response = client.get(format!("/person/{}", john_id)).dispatch().await;
|
||||
assert_eq!(person_response.status(), Status::Ok);
|
||||
let person_data: Option<Person> =
|
||||
serde_json::from_str(&person_response.into_string().await.unwrap()).unwrap();
|
||||
|
||||
// Verify that the data matches what was inserted.
|
||||
assert!(person_data.is_some());
|
||||
let person = person_data.unwrap();
|
||||
assert_eq!(person.name, "John Doe");
|
||||
|
||||
// Cleanup
|
||||
delete_person(&client, john_id).await;
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_person() {
|
||||
run_test!(|client| {
|
||||
let john_id = 1;
|
||||
|
||||
// Update John Doe to Jane Doe
|
||||
update_person(&client, john_id, "Jane Doe").await;
|
||||
|
||||
// Verify update
|
||||
let updated_person = read_person(&client, john_id).await;
|
||||
assert_eq!(updated_person.name, "Jane Doe");
|
||||
|
||||
// Cleanup
|
||||
delete_person(&client, john_id).await;
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insertion_deletion() {
|
||||
run_test!(|client| {
|
||||
// Get the person before making changes.
|
||||
let init_persons = query_persons(&client).await;
|
||||
let john_id = 1;
|
||||
// Issue a request to insert a new person.
|
||||
client
|
||||
.post(format!("/person/{}", john_id))
|
||||
.header(ContentType::JSON)
|
||||
.body(r#"{"name":"John Doe"}"#)
|
||||
.dispatch()
|
||||
.await;
|
||||
|
||||
// Ensure we have one more person in the database.
|
||||
let new_persons = query_persons(&client).await;
|
||||
assert_eq!(new_persons.len(), init_persons.len() + 1);
|
||||
|
||||
// Ensure the person is what we expect.
|
||||
let john = &new_persons[0];
|
||||
assert_eq!(john.name, "John Doe");
|
||||
|
||||
// Issue a request to delete the person.
|
||||
delete_person(&client, john_id).await;
|
||||
|
||||
// Ensure it's gone.
|
||||
let final_persons = query_persons(&client).await;
|
||||
assert_eq!(final_persons.len(), init_persons.len());
|
||||
if !final_persons.is_empty() {
|
||||
assert_ne!(final_persons[0].name, "John Doe");
|
||||
}
|
||||
|
||||
delete_all_persons(&client).await;
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue