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

129 lines
4.1 KiB
Python
Raw Normal View History

"""Test cases for the SQL module in the Numinar coding project backend."""
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 sqlmodel import SQLModel
# Assuming the module is named `database.py` and contains the provided code
from backend.sql import create_db_and_tables
from backend.sql import engine
from backend.sql 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.sql.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
def test_create_db_and_tables() -> None:
"""Test the create_db_and_tables function.
Verifies that the function correctly calls SQLModel.metadata.create_all with
the synchronous engine.
"""
with patch.object(SQLModel.metadata, "create_all") as mock_create_all:
create_db_and_tables()
mock_create_all.assert_called_once_with(engine.sync_engine)