mirror of
https://github.com/xlorepdarkhelm/numinar-coding-project.git
synced 2026-09-06 05:38:25 -04:00
171 lines
5.3 KiB
Python
171 lines
5.3 KiB
Python
"""Unit tests for the backend.services.users module."""
|
|
|
|
import logging
|
|
from collections.abc import Generator
|
|
from unittest.mock import AsyncMock
|
|
from unittest.mock import MagicMock
|
|
from unittest.mock import patch
|
|
|
|
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
|
|
|
|
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.mark.asyncio
|
|
async def test_get_users_success(
|
|
async_session: AsyncSession, sample_users: UserList, mock_logger: MockLogger
|
|
) -> 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
|
|
async def test_get_users_empty(
|
|
async_session: AsyncSession, mock_logger: MockLogger
|
|
) -> 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
|
|
async def test_get_users_database_error(
|
|
async_session: AsyncSession, mock_logger: MockLogger
|
|
) -> 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(
|
|
"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: MockLogger
|
|
) -> 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(
|
|
"email",
|
|
[
|
|
"nonexistent@example.com",
|
|
"invalid@domain.com",
|
|
],
|
|
ids=["nonexistent_email", "invalid_email"],
|
|
)
|
|
async def test_get_user_not_found(
|
|
async_session: AsyncSession, mock_logger: MockLogger, 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
|
|
async def test_get_user_database_error(
|
|
async_session: AsyncSession, mock_logger: MockLogger
|
|
) -> 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)
|
|
)
|