Files
conference-room-booking-system/backend/tests/routers/test_users.py
T

173 lines
5.9 KiB
Python
Raw Normal View History

2025-08-24 16:37:21 -04:00
"""Unit tests for the backend.routers.users module."""
from unittest.mock import ANY
from unittest.mock import AsyncMock
from unittest.mock import MagicMock
from unittest.mock import patch
import pytest
2025-08-27 15:51:05 -04:00
from httpx import AsyncClient
2025-08-24 16:37:21 -04:00
from sqlalchemy.exc import NoResultFound
from sqlalchemy.exc import SQLAlchemyError
from backend.models import User
2025-08-26 17:20:16 -04:00
from backend.models import UserList
2025-08-24 16:37:21 -04:00
@pytest.mark.asyncio
2025-08-25 21:38:31 -04:00
@pytest.mark.parametrize("mock_logger", ["backend.routers.users"], indirect=True)
2025-08-24 16:37:21 -04:00
async def test_read_users_success(
2025-08-27 15:51:05 -04:00
client: AsyncClient, sample_users: UserList, mock_logger: MagicMock
2025-08-24 16:37:21 -04:00
) -> None:
"""Test successful retrieval of all users via GET /users/.
Verifies that the endpoint returns the expected list of users with a 200 status.
2025-08-26 15:47:08 -04:00
Args:
client: The FastAPI test client for making HTTP requests.
sample_users: The mocked list of users to return.
mock_logger: The mocked logger instance.
2025-08-24 16:37:21 -04:00
"""
with patch("backend.routers.users.get_users", new=AsyncMock()) as mock_get_users:
mock_get_users.return_value = sample_users
2025-08-27 15:51:05 -04:00
response = await client.get("/users/")
2025-08-24 16:37:21 -04:00
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
2025-08-25 21:38:31 -04:00
@pytest.mark.parametrize("mock_logger", ["backend.routers.users"], indirect=True)
2025-08-27 15:51:05 -04:00
async def test_read_users_empty(client: AsyncClient, mock_logger: MagicMock) -> None:
2025-08-24 16:37:21 -04:00
"""Test retrieval of users when none exist via GET /users/.
Verifies that the endpoint returns an empty list with a 200 status.
2025-08-26 15:47:08 -04:00
Args:
client: The FastAPI test client for making HTTP requests.
mock_logger: The mocked logger instance.
2025-08-24 16:37:21 -04:00
"""
with patch("backend.routers.users.get_users", new=AsyncMock()) as mock_get_users:
mock_get_users.return_value = []
2025-08-27 15:51:05 -04:00
response = await client.get("/users/")
2025-08-24 16:37:21 -04:00
assert response.status_code == 200
assert response.json() == []
mock_get_users.assert_called_once()
@pytest.mark.asyncio
2025-08-25 21:38:31 -04:00
@pytest.mark.parametrize("mock_logger", ["backend.routers.users"], indirect=True)
2025-08-24 16:37:21 -04:00
async def test_read_users_database_error(
2025-08-27 15:51:05 -04:00
client: AsyncClient, mock_logger: MagicMock
2025-08-24 16:37:21 -04:00
) -> None:
"""Test handling of database errors in GET /users/.
Verifies that the endpoint returns a 500 status on database failure.
2025-08-26 15:47:08 -04:00
Args:
client: The FastAPI test client for making HTTP requests.
mock_logger: The mocked logger instance.
2025-08-24 16:37:21 -04:00
"""
with patch("backend.routers.users.get_users", new=AsyncMock()) as mock_get_users:
2025-08-24 21:20:24 -04:00
mock_get_users.side_effect = SQLAlchemyError()
2025-08-24 16:37:21 -04:00
2025-08-27 15:51:05 -04:00
response = await client.get("/users/")
2025-08-24 16:37:21 -04:00
assert response.status_code == 500
2025-08-24 21:20:24 -04:00
assert "detail" in response.json()
2025-08-24 16:37:21 -04:00
mock_get_users.assert_called_once()
@pytest.mark.asyncio
2025-08-25 21:38:31 -04:00
@pytest.mark.parametrize("mock_logger", ["backend.routers.users"], indirect=True)
2025-08-24 16:37:21 -04:00
@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(
2025-08-27 15:51:05 -04:00
client: AsyncClient, email: str, expected_name: str, mock_logger: MagicMock
2025-08-24 16:37:21 -04:00
) -> 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.
2025-08-26 15:47:08 -04:00
Args:
client: The FastAPI test client for making HTTP requests.
email: The email of the user to retrieve.
expected_name: The expected name of the user.
mock_logger: The mocked logger instance.
2025-08-24 16:37:21 -04:00
"""
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
2025-08-27 15:51:05 -04:00
response = await client.get(f"/users/{email}")
2025-08-24 16:37:21 -04:00
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
2025-08-25 21:38:31 -04:00
@pytest.mark.parametrize("mock_logger", ["backend.routers.users"], indirect=True)
2025-08-24 16:37:21 -04:00
@pytest.mark.parametrize(
"email",
["nonexistent@example.com", "invalid@domain.com"],
ids=["nonexistent_email", "invalid_email"],
)
async def test_read_user_not_found(
2025-08-27 15:51:05 -04:00
client: AsyncClient, email: str, mock_logger: MagicMock
2025-08-24 16:37:21 -04:00
) -> 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.
2025-08-26 15:47:08 -04:00
Args:
client: The FastAPI test client for making HTTP requests.
email: The email of the user to retrieve.
mock_logger: The mocked logger instance.
2025-08-24 16:37:21 -04:00
"""
with patch("backend.routers.users.get_user", new=AsyncMock()) as mock_get_user:
2025-08-24 21:20:24 -04:00
mock_get_user.side_effect = NoResultFound()
2025-08-24 16:37:21 -04:00
2025-08-27 15:51:05 -04:00
response = await client.get(f"/users/{email}")
2025-08-24 16:37:21 -04:00
assert response.status_code == 404
2025-08-24 21:20:24 -04:00
assert "detail" in response.json()
2025-08-24 16:37:21 -04:00
mock_get_user.assert_called_once_with(ANY, email)
@pytest.mark.asyncio
2025-08-25 21:38:31 -04:00
@pytest.mark.parametrize("mock_logger", ["backend.routers.users"], indirect=True)
2025-08-24 16:37:21 -04:00
async def test_read_user_database_error(
2025-08-27 15:51:05 -04:00
client: AsyncClient, mock_logger: MagicMock
2025-08-24 16:37:21 -04:00
) -> None:
"""Test handling of database errors in GET /users/{email}.
Verifies that the endpoint returns a 500 status on database failure.
2025-08-26 15:47:08 -04:00
Args:
client: The FastAPI test client for making HTTP requests.
mock_logger: The mocked logger instance.
2025-08-24 16:37:21 -04:00
"""
email = "user1@example.com"
with patch("backend.routers.users.get_user", new=AsyncMock()) as mock_get_user:
2025-08-24 21:20:24 -04:00
mock_get_user.side_effect = SQLAlchemyError()
2025-08-24 16:37:21 -04:00
2025-08-27 15:51:05 -04:00
response = await client.get(f"/users/{email}")
2025-08-24 16:37:21 -04:00
assert response.status_code == 500
2025-08-24 21:20:24 -04:00
assert "detail" in response.json()
2025-08-24 16:37:21 -04:00
mock_get_user.assert_called_once_with(ANY, email)