1+ """Utility functions for asserting HTTP responses in tests."""
2+
13from typing import Any , Optional , TypeVar , get_args , get_origin , overload
24
35from fastapi import HTTPException
@@ -26,6 +28,19 @@ def assert_res_success(
2628 * ,
2729 status : Optional [int ] = 200 ,
2830) -> T | list [T ]:
31+ """
32+ Assert that a response is a successful response. Validates and converts to the expected model type.
33+
34+ Args:
35+ res: The HTTP response to check
36+ ExpectedModel: The expected Pydantic model type (or list of model type) of the response data
37+ status: Optional expected HTTP status code (default 200)
38+
39+ Returns:
40+ The response data converted to the expected model type
41+ e.g. `assert_res_success(res, User)` returns `User`
42+ `assert_res_success(res, [User])` returns `list[User]`
43+ """
2944 if status is not None :
3045 assert res .status_code == status , (
3146 f"Expected status { status } , got { res .status_code } . Response: { res .text } "
@@ -44,14 +59,17 @@ def assert_res_success(
4459 assert data is not None , "Expected response data but got None"
4560
4661 model_origin = get_origin (ExpectedModel )
62+
63+ # List model case
4764 if model_origin is list :
4865 assert isinstance (data , list ), f"Expected list response but got { type (data ).__name__ } "
4966
67+ # Get the model type inside the list
5068 args = get_args (ExpectedModel )
5169 assert args is not None , "Expected type args for list model but got None"
5270 assert len (args ) > 0 , "Expected at least one type arg for list model but got empty args"
53-
5471 inner_model = args [0 ]
72+
5573 inner_fields = set (inner_model .model_fields .keys ())
5674 for item in data :
5775 extra = set (item .keys ()) - inner_fields
@@ -69,6 +87,16 @@ def assert_res_success(
6987
7088
7189def assert_res_failure (res : Response , expected_error : HTTPException ) -> dict [str , Any ]:
90+ """
91+ Assert that a response is a failure response matching the expected HTTPException.
92+
93+ Args:
94+ res: The HTTP response to check
95+ expected_error: The expected HTTPException instance representing the error
96+
97+ Returns:
98+ The response data dict containing the error details
99+ """
72100 assert res .status_code == expected_error .status_code , (
73101 f"Expected status { expected_error .status_code } , got { res .status_code } . Response: { res .text } "
74102 )
0 commit comments