mirror of
https://github.com/xlorepdarkhelm/numinar-coding-project.git
synced 2026-09-09 17:45:35 -04:00
121 lines
3.7 KiB
Python
121 lines
3.7 KiB
Python
"""Unit tests for the backend.routers.users module."""
|
|
|
|
from typing import Any
|
|
|
|
import pytest
|
|
import sqlalchemy.exc
|
|
from httpx import AsyncClient
|
|
from sqlalchemy.exc import SQLAlchemyError
|
|
|
|
from backend.dependencies.users import get_users_service
|
|
from backend.main import app
|
|
from backend.models import User
|
|
from backend.types import UserData
|
|
|
|
|
|
# Useful constants for users router tests
|
|
USERS_SUCCESS_STATUS = 200
|
|
USERS_DB_ERROR_STATUS = 500
|
|
USERS_NOT_FOUND_STATUS = 404
|
|
USERS_DB_ERROR_DETAIL = "Database error"
|
|
USERS_NOT_FOUND_DETAIL = "User not found"
|
|
USERS_UNEXPECTED_ERROR_DETAIL = "An unexpected error occurred"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("has_users", [True, False], ids=["users_exist", "users_empty"])
|
|
async def test_read_users_parametrized(
|
|
client: AsyncClient,
|
|
sample_users: list[User],
|
|
sample_users_data: list[UserData],
|
|
has_users: bool,
|
|
) -> None:
|
|
"""Test GET /users/ for success and empty list cases.
|
|
|
|
Args:
|
|
client: The FastAPI test client for making HTTP requests.
|
|
sample_users: The list of sample User objects.
|
|
sample_users_data: The expected response data for users.
|
|
has_users: Whether to return users or an empty list.
|
|
|
|
Asserts:
|
|
- Response status code is USERS_SUCCESS_STATUS.
|
|
- Response JSON matches expected user data or empty list.
|
|
"""
|
|
|
|
async def mock_get_users(*args: Any, **kwargs: Any) -> list[User]:
|
|
return sample_users if has_users else []
|
|
|
|
app.dependency_overrides[get_users_service] = lambda: mock_get_users
|
|
response = await client.get("/users/")
|
|
assert response.status_code == USERS_SUCCESS_STATUS
|
|
expected = sample_users_data if has_users else []
|
|
assert response.json() == expected
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_read_users_database_error(
|
|
client: AsyncClient,
|
|
) -> None:
|
|
"""Test GET /users/ for database error.
|
|
|
|
Args:
|
|
client: The FastAPI test client for making HTTP requests.
|
|
|
|
Asserts:
|
|
- Response status code is USERS_DB_ERROR_STATUS.
|
|
- Response JSON contains 'detail'.
|
|
"""
|
|
|
|
async def mock_get_users(*args: Any, **kwargs: Any) -> None:
|
|
raise SQLAlchemyError()
|
|
|
|
app.dependency_overrides[get_users_service] = lambda: mock_get_users
|
|
response = await client.get("/users/")
|
|
assert response.status_code == USERS_DB_ERROR_STATUS
|
|
assert "detail" in response.json()
|
|
|
|
|
|
# Parametrized error path tests for GET /users/
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize(
|
|
"exception_to_raise,expected_status,expected_detail",
|
|
[
|
|
(
|
|
sqlalchemy.exc.NoResultFound(),
|
|
USERS_NOT_FOUND_STATUS,
|
|
USERS_NOT_FOUND_DETAIL,
|
|
),
|
|
(Exception("fail"), USERS_DB_ERROR_STATUS, USERS_UNEXPECTED_ERROR_DETAIL),
|
|
],
|
|
ids=["no_result_found", "unexpected_error"],
|
|
)
|
|
async def test_read_users_error_paths(
|
|
client: AsyncClient,
|
|
exception_to_raise: Exception,
|
|
expected_status: int,
|
|
expected_detail: str,
|
|
) -> None:
|
|
"""Test GET /users/ for error paths: NoResultFound (404) and generic exception (500).
|
|
|
|
Args:
|
|
client: The FastAPI test client for making HTTP requests.
|
|
exception_to_raise: The exception to raise in the service dependency.
|
|
expected_status: The expected HTTP status code.
|
|
expected_detail: The expected error detail message.
|
|
|
|
Asserts:
|
|
- Response status code matches expected_status.
|
|
- Response JSON 'detail' matches expected_detail.
|
|
"""
|
|
|
|
async def mock_get_users(*args: Any, **kwargs: Any) -> None:
|
|
raise exception_to_raise
|
|
|
|
app.dependency_overrides[get_users_service] = lambda: mock_get_users
|
|
response = await client.get("/users/")
|
|
assert response.status_code == expected_status
|
|
assert response.json()["detail"] == expected_detail
|