Files
conference-room-booking-system/backend/tests/services/test_users.py
2025-08-25 21:38:31 -04:00

155 lines
5.1 KiB
Python

"""Unit tests for the backend.services.users module."""
from unittest.mock import AsyncMock
from unittest.mock import MagicMock
import pytest
from sqlalchemy import select
from sqlalchemy.exc import NoResultFound
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.ext.asyncio import AsyncSession
from backend.models import User
from backend.services.users import UserList
from backend.services.users import get_user
from backend.services.users import get_users
@pytest.mark.asyncio
@pytest.mark.parametrize("mock_logger", ["backend.services.users"], indirect=True)
async def test_get_users_success(
async_session: AsyncSession, sample_users: UserList, mock_logger: MagicMock
) -> None:
"""Test successful retrieval of all users from the database.
Verifies that get_users returns the expected list of users and constructs
the correct SQLAlchemy query.
"""
mock_scalars_result = AsyncMock()
mock_scalars_result.all = MagicMock(return_value=sample_users)
mock_scalars = AsyncMock(return_value=mock_scalars_result)
async_session.scalars = mock_scalars
result: UserList = await get_users(async_session)
assert isinstance(result, list)
assert len(result) == 2
assert result == sample_users
async_session.scalars.assert_called_once()
assert async_session.scalars.call_args.args[0].compare(select(User))
@pytest.mark.asyncio
@pytest.mark.parametrize("mock_logger", ["backend.services.users"], indirect=True)
async def test_get_users_empty(
async_session: AsyncSession, mock_logger: MagicMock
) -> None:
"""Test retrieval of users when the database is empty.
Verifies that get_users returns an empty list when no users are found.
"""
mock_scalars_result = AsyncMock()
mock_scalars_result.all = MagicMock(return_value=[])
mock_scalars = AsyncMock(return_value=mock_scalars_result)
async_session.scalars = mock_scalars
result: UserList = await get_users(async_session)
assert isinstance(result, list)
assert len(result) == 0
async_session.scalars.assert_called_once()
assert async_session.scalars.call_args.args[0].compare(select(User))
@pytest.mark.asyncio
@pytest.mark.parametrize("mock_logger", ["backend.services.users"], indirect=True)
async def test_get_users_database_error(
async_session: AsyncSession, mock_logger: MagicMock
) -> None:
"""Test handling of database errors in get_users.
Verifies that get_users raises an exception and logs an error on database failure.
"""
async_session.scalars = AsyncMock(side_effect=SQLAlchemyError("Database error"))
with pytest.raises(SQLAlchemyError):
await get_users(async_session)
async_session.scalars.assert_called_once()
@pytest.mark.asyncio
@pytest.mark.parametrize("mock_logger", ["backend.services.users"], indirect=True)
@pytest.mark.parametrize(
"email, expected_name",
[
("user1@example.com", "User One"),
("user2@example.com", "User Two"),
],
ids=["user1", "user2"],
)
async def test_get_user_success(
async_session: AsyncSession, email: str, expected_name: str, mock_logger: MagicMock
) -> None:
"""Test successful retrieval of a user by email.
Verifies that get_user returns the correct user and constructs the correct query.
"""
user = User(email=email, name=expected_name)
async_session.scalar = AsyncMock(return_value=user)
result: User = await get_user(async_session, email)
assert result.email == email
assert result.name == expected_name
async_session.scalar.assert_called_once()
assert async_session.scalar.call_args.args[0].compare(
select(User).where(User.email == email)
)
@pytest.mark.asyncio
@pytest.mark.parametrize("mock_logger", ["backend.services.users"], indirect=True)
@pytest.mark.parametrize(
"email",
[
"nonexistent@example.com",
"invalid@domain.com",
],
ids=["nonexistent_email", "invalid_email"],
)
async def test_get_user_not_found(
async_session: AsyncSession, mock_logger: MagicMock, email: str
) -> None:
"""Test handling of non-existent user in get_user.
Verifies that get_user raises NoResultFound and logs an error when the user is not found.
"""
async_session.scalar = AsyncMock(return_value=None)
with pytest.raises(NoResultFound):
await get_user(async_session, email)
async_session.scalar.assert_called_once()
assert async_session.scalar.call_args.args[0].compare(
select(User).where(User.email == email)
)
@pytest.mark.asyncio
@pytest.mark.parametrize("mock_logger", ["backend.services.users"], indirect=True)
async def test_get_user_database_error(
async_session: AsyncSession, mock_logger: MagicMock
) -> None:
"""Test handling of database errors in get_user.
Verifies that get_user raises an exception and logs an error on database failure.
"""
email: str = "user1@example.com"
async_session.scalar = AsyncMock(side_effect=SQLAlchemyError("Database error"))
with pytest.raises(SQLAlchemyError):
await get_user(async_session, email)
async_session.scalar.assert_called_once()
assert async_session.scalar.call_args.args[0].compare(
select(User).where(User.email == email)
)