Files
conference-room-booking-system/backend/tests/test_db.py

118 lines
3.7 KiB
Python

"""Test cases for the SQL module in the Numinar coding project backend.
This primarily focuses on testing the sessionize decorator to ensure it correctly
manages database sessions for asynchronous functions.i
"""
from typing import Any
from typing import AsyncGenerator
from unittest.mock import AsyncMock
from unittest.mock import patch
import pytest
import pytest_asyncio
from sqlalchemy.ext.asyncio import AsyncSession
from backend.db import sessionize
@pytest_asyncio.fixture
async def mock_async_sessionmaker() -> AsyncGenerator[AsyncMock, None]:
"""Fixture to mock the async sessionmaker for testing sessionize decorator.
Yields:
AsyncMock: A mocked async sessionmaker that returns a mocked AsyncSession.
"""
with patch("backend.db.async_sessionmaker") as mock_sessionmaker:
mock_session: AsyncMock = AsyncMock(spec=AsyncSession)
mock_sessionmaker.return_value = AsyncMock(return_value=mock_session)
yield mock_sessionmaker
@pytest.mark.asyncio
async def test_sessionize_decorator_with_no_session(
mock_async_sessionmaker: AsyncMock,
) -> None:
"""Test the sessionize decorator when no session is provided.
Verifies that the decorator creates a new session and passes it to the function,
and that the function executes correctly.
"""
@sessionize
async def test_func(session: AsyncSession | None = None) -> str:
setattr(test_func, "session", session) # noqa: B010
return "success"
result: str = await test_func()
assert result == "success"
assert test_func.session is not None # type: ignore
@pytest.mark.asyncio
async def test_sessionize_decorator_with_session(
mock_async_sessionmaker: AsyncMock,
) -> None:
"""Test the sessionize decorator when a session is provided.
Verifies that the decorator uses the provided session without creating a new one,
and that the function executes correctly.
"""
@sessionize
async def test_func(session: AsyncSession | None = None) -> str:
setattr(test_func, "session", session) # noqa: B010
return "success"
mock_session: AsyncMock = AsyncMock(spec=AsyncSession)
result: str = await test_func(session=mock_session)
assert result == "success"
assert mock_session is test_func.session # type: ignore
@pytest.mark.asyncio
async def test_sessionize_decorator_error_handling(
mock_async_sessionmaker: AsyncMock,
) -> None:
"""Test the sessionize decorator's error handling.
Verifies that the decorator properly handles exceptions raised by the decorated
function and ensures the session is created when none is provided.
"""
@sessionize
async def test_func(session: AsyncSession) -> None:
setattr(test_func, "session", session) # noqa: B010
raise ValueError("Test error")
with pytest.raises(ValueError, match="Test error"):
await test_func()
@pytest.mark.asyncio
@pytest.mark.parametrize(
"func_return_value",
["result1", 42, None],
ids=["string", "integer", "none"],
)
async def test_sessionize_decorator_return_types(
mock_async_sessionmaker: AsyncMock, func_return_value: Any
) -> None:
"""Test the sessionize decorator with different return types.
Verifies that the decorator correctly handles various return types from the
decorated function.
Args:
mock_async_sessionmaker: Mocked async sessionmaker.
func_return_value: The value to be returned by the test function.
"""
@sessionize
async def test_func(session: AsyncSession) -> Any:
setattr(test_func, "session", session) # noqa: B010
return func_return_value
result: Any = await test_func()
assert result == func_return_value