mirror of
https://github.com/xlorepdarkhelm/numinar-coding-project.git
synced 2026-09-06 00:48:26 -04:00
167 lines
5.4 KiB
Python
167 lines
5.4 KiB
Python
"""Unit tests for the backend.routers.users module."""
|
|
|
|
import logging
|
|
from collections.abc import Generator
|
|
from unittest.mock import ANY
|
|
from unittest.mock import AsyncMock
|
|
from unittest.mock import MagicMock
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
from sqlalchemy.exc import NoResultFound
|
|
from sqlalchemy.exc import SQLAlchemyError
|
|
|
|
from backend.main import app
|
|
from backend.models import User
|
|
from backend.services.users import UserList
|
|
|
|
from ..conftest import MockLogger
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def mock_logger() -> Generator[MockLogger, None, None]:
|
|
"""Fixture to mock the logger used in the users service."""
|
|
mock_logger_instance = MagicMock(spec=logging.Logger)
|
|
with patch("backend.services.users.logger", mock_logger_instance):
|
|
yield mock_logger_instance
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_users() -> UserList:
|
|
"""Fixture to provide sample User objects for testing."""
|
|
return [
|
|
User(email="user1@example.com", name="User One"),
|
|
User(email="user2@example.com", name="User Two"),
|
|
]
|
|
|
|
|
|
@pytest.fixture
|
|
def client() -> TestClient:
|
|
"""Fixture to provide a FastAPI TestClient for testing endpoints."""
|
|
return TestClient(app)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_read_users_success(
|
|
client: TestClient, sample_users: UserList, mock_logger: MockLogger
|
|
) -> None:
|
|
"""Test successful retrieval of all users via GET /users/.
|
|
|
|
Verifies that the endpoint returns the expected list of users with a 200 status.
|
|
"""
|
|
with patch("backend.routers.users.get_users", new=AsyncMock()) as mock_get_users:
|
|
mock_get_users.return_value = sample_users
|
|
|
|
response = client.get("/users/")
|
|
|
|
assert response.status_code == 200
|
|
assert response.json() == [
|
|
{"email": "user1@example.com", "name": "User One"},
|
|
{"email": "user2@example.com", "name": "User Two"},
|
|
]
|
|
mock_get_users.assert_called_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_read_users_empty(client: TestClient, mock_logger: MockLogger) -> None:
|
|
"""Test retrieval of users when none exist via GET /users/.
|
|
|
|
Verifies that the endpoint returns an empty list with a 200 status.
|
|
"""
|
|
with patch("backend.routers.users.get_users", new=AsyncMock()) as mock_get_users:
|
|
mock_get_users.return_value = []
|
|
|
|
response = client.get("/users/")
|
|
|
|
assert response.status_code == 200
|
|
assert response.json() == []
|
|
mock_get_users.assert_called_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_read_users_database_error(
|
|
client: TestClient, mock_logger: MockLogger
|
|
) -> None:
|
|
"""Test handling of database errors in GET /users/.
|
|
|
|
Verifies that the endpoint returns a 500 status on database failure.
|
|
"""
|
|
with patch("backend.routers.users.get_users", new=AsyncMock()) as mock_get_users:
|
|
mock_get_users.side_effect = SQLAlchemyError("Database error")
|
|
|
|
response = client.get("/users/")
|
|
|
|
assert response.status_code == 500
|
|
assert response.json() == {"detail": "Database error occurred"}
|
|
mock_get_users.assert_called_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize(
|
|
"email, expected_name",
|
|
[
|
|
("user1@example.com", "User One"),
|
|
("user2@example.com", "User Two"),
|
|
],
|
|
ids=["user1", "user2"],
|
|
)
|
|
async def test_read_user_success(
|
|
client: TestClient, email: str, expected_name: str, mock_logger: MockLogger
|
|
) -> None:
|
|
"""Test successful retrieval of a user by email via GET /users/{email}.
|
|
|
|
Verifies that the endpoint returns the correct user with a 200 status.
|
|
"""
|
|
user = User(email=email, name=expected_name)
|
|
with patch("backend.routers.users.get_user", new=AsyncMock()) as mock_get_user:
|
|
mock_get_user.return_value = user
|
|
|
|
response = client.get(f"/users/{email}")
|
|
|
|
assert response.status_code == 200
|
|
assert response.json() == {"email": email, "name": expected_name}
|
|
mock_get_user.assert_called_once_with(ANY, email)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize(
|
|
"email",
|
|
["nonexistent@example.com", "invalid@domain.com"],
|
|
ids=["nonexistent_email", "invalid_email"],
|
|
)
|
|
async def test_read_user_not_found(
|
|
client: TestClient, email: str, mock_logger: MockLogger
|
|
) -> None:
|
|
"""Test handling of non-existent user in GET /users/{email}.
|
|
|
|
Verifies that the endpoint returns a 404 status when the user is not found.
|
|
"""
|
|
with patch("backend.routers.users.get_user", new=AsyncMock()) as mock_get_user:
|
|
mock_get_user.side_effect = NoResultFound(f"User with email {email} not found")
|
|
|
|
response = client.get(f"/users/{email}")
|
|
|
|
assert response.status_code == 404
|
|
assert response.json() == {"detail": f"User with email {email} not found"}
|
|
mock_get_user.assert_called_once_with(ANY, email)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_read_user_database_error(
|
|
client: TestClient, mock_logger: MockLogger
|
|
) -> None:
|
|
"""Test handling of database errors in GET /users/{email}.
|
|
|
|
Verifies that the endpoint returns a 500 status on database failure.
|
|
"""
|
|
email = "user1@example.com"
|
|
with patch("backend.routers.users.get_user", new=AsyncMock()) as mock_get_user:
|
|
mock_get_user.side_effect = SQLAlchemyError("Database error")
|
|
|
|
response = client.get(f"/users/{email}")
|
|
|
|
assert response.status_code == 500
|
|
assert response.json() == {"detail": "Database error occurred"}
|
|
mock_get_user.assert_called_once_with(ANY, email)
|