From bba9647ddc4ff063f66f49abfc0e924b5bfe0873 Mon Sep 17 00:00:00 2001 From: Christopher Biscardi Date: Sun, 17 Oct 2021 07:22:01 -0700 Subject: [PATCH] Utility functions for tests We have a few code paths that some url paths can run when we receive invalid input. We'll write one new test: `handler_handles_empty_pokemon` . The new test, in addition to the one we've already written needs an `ApiGatewayProxyRequest` which is quite large to write out each time. Inside of the `tests` sub-module we can add a helper function to construct and return a new `ApiGatewayProxyRequest`. The `fake_request` function will accept a `path` that we use in the `path: Some(path)` field of the `ApiGatewayProxyRequest`. ```rust fn fake_request( path: String, ) -> ApiGatewayProxyRequest { ApiGatewayProxyRequest { resource: None, path: Some(path), http_method: Method::GET, headers: HeaderMap::new(), multi_value_headers: HeaderMap::new(), query_string_parameters: HashMap::new(), multi_value_query_string_parameters: HashMap::new(), path_parameters: HashMap::new(), stage_variables: HashMap::new(), request_context: ApiGatewayProxyRequestContext { account_id: None, resource_id: None, operation_name: None, stage: None, domain_name: None, domain_prefix: None, request_id: None, protocol: None, identity: ApiGatewayRequestIdentity { cognito_identity_pool_id: None, account_id: None, cognito_identity_id: None, caller: None, api_key: None, api_key_id: None, access_key: None, source_ip: None, cognito_authentication_type: None, cognito_authentication_provider: None, user_arn: None, user_agent: None, user: None, }, resource_path: None, authorizer: HashMap::new(), http_method: Method::GET, request_time: None, request_time_epoch: 0, apiid: None, }, body: None, is_base64_encoded: Some(false), } } ``` and we can use it in the `handler_handles` test. ```rust async fn handler_handles() { let event = fake_request( "/api/pokemon/bulbasaur".to_string(), ); assert_eq!( handler(event.clone(), Context::default()) .await .unwrap(), ApiGatewayProxyResponse { status_code: 200, headers: HeaderMap::new(), multi_value_headers: HeaderMap::new(), body: Some(Body::Text( serde_json::to_string(&PokemonHp { name: String::from("Bulbasaur"), hp: 45 },) .unwrap() )), is_base64_encoded: Some(false), } ) } ``` Our new test will panic because of the `todo` macro, so we can use the `should_panic` attribute macro to test against the expected panic message. The test will exercise the `400` codepath, which happens when the path doesn't include a Pokemon name. We could return an empty response as if we hadn't found a Pokemon, but it's most likely that an empty path segment is a client mistake, having passed in an empty string or misconstructed the path. ```rust async fn handler_handles_empty_pokemon() { let event = fake_request("/api/pokemon//".to_string()); handler(event.clone(), Context::default()) .await .unwrap(); } ``` All tests should pass at this point --- crates/pokemon-api/src/main.rs | 64 +++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/crates/pokemon-api/src/main.rs b/crates/pokemon-api/src/main.rs index ec4dbeb..dd7096f 100644 --- a/crates/pokemon-api/src/main.rs +++ b/crates/pokemon-api/src/main.rs @@ -78,11 +78,46 @@ mod tests { #[tokio::test] async fn handler_handles() { - let event = ApiGatewayProxyRequest { + let event = fake_request( + "/api/pokemon/bulbasaur".to_string(), + ); + + assert_eq!( + handler(event.clone(), Context::default()) + .await + .unwrap(), + ApiGatewayProxyResponse { + status_code: 200, + headers: HeaderMap::new(), + multi_value_headers: HeaderMap::new(), + body: Some(Body::Text( + serde_json::to_string(&PokemonHp { + name: String::from("Bulbasaur"), + hp: 45 + },) + .unwrap() + )), + is_base64_encoded: Some(false), + } + ) + } + + #[tokio::test] + #[should_panic(expected = "not yet implemented")] + async fn handler_handles_empty_pokemon() { + let event = + fake_request("/api/pokemon//".to_string()); + handler(event.clone(), Context::default()) + .await + .unwrap(); + } + + fn fake_request( + path: String, + ) -> ApiGatewayProxyRequest { + ApiGatewayProxyRequest { resource: None, - path: Some( - "/api/pokemon/bulbasaur".to_string(), - ), + path: Some(path), http_method: Method::GET, headers: HeaderMap::new(), multi_value_headers: HeaderMap::new(), @@ -126,25 +161,6 @@ mod tests { }, body: None, is_base64_encoded: Some(false), - }; - - assert_eq!( - handler(event.clone(), Context::default()) - .await - .unwrap(), - ApiGatewayProxyResponse { - status_code: 200, - headers: HeaderMap::new(), - multi_value_headers: HeaderMap::new(), - body: Some(Body::Text( - serde_json::to_string(&PokemonHp { - name: String::from("Bulbasaur"), - hp: 45 - },) - .unwrap() - )), - is_base64_encoded: Some(false), - } - ) + } } }