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
.
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.
#[tokio::test]
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.
#[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();
}
All tests should pass at this point