Hello, Rustaceans. I'm building a CRUD app where users can join by just submitting a username or a referral code from a previously registered user(don't worry about auth security). The backend service is in Axum, Postgres and sqlx. I have written a username signup handler that looks like so:
#[debug_handler]
pub async fn signup_username(
ctx: Extension<ApiContext>,
Form(input): Form<UserBody<UsernameInput>>
) -> Result<Json<UserBody<User>>, ApiError> {
debug!("Received signup request for username: {}", input.user.username);
let referral_code = generate_referral_code(input.user.username.clone())?;
if input.user.username.is_empty(){
return Err(ApiError::MissingCredential);
} else {
debug!("Inserting user: {} with referral code: {}", input.user.username, referral_code);
let user = sqlx::query_as!(
User,
r#"
insert into users(username, referral_code)
values($1, $2)
returning username, id, referral_code, referred_by, invited_users_count, created_at, updated_at
"#,
input.user.username,
referral_code
)
.fetch_one(&ctx.0.db)
.await
.map_err(| err | {
error!("error trying to insert into db: {err}");
ApiError::InternalServerError
})?;
debug!("Successfully inserted user: {:?}", user);
Ok(Json(UserBody {
user,
}))
}
}
The handler takes an input of the type Form extractor and returns Json, or ApiError as output. I have the database table created and I try to insert the form input into the table to create a new user. The code compiles successfully. So I test it by trying to insert a new username to find out if the insertion works:
#[tokio::test]
async fn signup_returns_a_200_for_valid_form_data() {
let config: Config = Config::new();
let db_connection = PgPoolOptions::new()
.max_connections(5)
.connect(&config.database_url)
.await
.expect("Failed to connect to db");
let client = hyper::Client::new();
let body = hyper::Body::from("username=brook");
let request = hyper::Request::builder()
.method(hyper::Method::POST)
.uri("http://127.0.0.1:8080/users/signup-username")
.header("Content-Type", "application/x-www-form-urlencoded")
.body(body)
.expect("Failed to create request");
let response = client
.request(request)
.await
.expect("Failed to send request");
assert_eq!(response.status(), hyper::StatusCode::OK);
let saved = sqlx::query!(
"select username, referral_code from users where username = 'brook' ",
)
.fetch_one(&db_connection)
.await
.expect("Failed to fetch saved data");
assert_eq!(saved.username, "brook");
assert!(!saved.referral_code.is_empty());
}
But the first assert_eq
:
assert_eq!(response.status(), hyper::StatusCode::OK);
Fails with a 422 error code:
--- signup_returns_a_200_for_valid_form_data stdout ----
thread 'signup_returns_a_200_for_valid_form_data' panicked at 'assertion failed: `(left == right)`
left: `422`,
right: `200`', tests/signup.rs:35:5
I've added a couple of debug logs to the code to try and smoke out the bug, but I've had no success. What am I doing wrong?