mirror of
https://github.com/xlorepdarkhelm/numinar-coding-project.git
synced 2026-09-05 20:58:26 -04:00
375 lines
12 KiB
Python
375 lines
12 KiB
Python
"""Unit tests for the backend.services.rooms module."""
|
|
|
|
from typing import Any
|
|
from unittest.mock import AsyncMock
|
|
from unittest.mock import MagicMock
|
|
|
|
import pytest
|
|
from sqlalchemy import delete
|
|
from sqlalchemy import select
|
|
from sqlalchemy import update
|
|
from sqlalchemy.exc import NoResultFound
|
|
from sqlalchemy.exc import SQLAlchemyError
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from backend.models import Room
|
|
from backend.services.rooms import RoomList
|
|
from backend.services.rooms import delete_room
|
|
from backend.services.rooms import get_room
|
|
from backend.services.rooms import get_rooms
|
|
from backend.services.rooms import new_room
|
|
from backend.services.rooms import update_room
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
|
async def test_get_rooms_success(
|
|
async_session: AsyncSession, sample_rooms: RoomList, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test successful retrieval of all rooms from the database.
|
|
|
|
Verifies that get_rooms returns the expected list of rooms and constructs
|
|
the correct SQLAlchemy query.
|
|
"""
|
|
mock_scalars_result = AsyncMock()
|
|
mock_scalars_result.all = MagicMock(return_value=sample_rooms)
|
|
mock_scalars = AsyncMock(return_value=mock_scalars_result)
|
|
async_session.scalars = mock_scalars
|
|
|
|
result: RoomList = await get_rooms(async_session)
|
|
|
|
assert isinstance(result, list)
|
|
assert len(result) == 2
|
|
assert result == sample_rooms
|
|
async_session.scalars.assert_called_once()
|
|
assert async_session.scalars.call_args.args[0].compare(select(Room))
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
|
async def test_get_rooms_empty(
|
|
async_session: AsyncSession, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test retrieval of rooms when the database is empty.
|
|
|
|
Verifies that get_rooms returns an empty list when no rooms 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: RoomList = await get_rooms(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(Room))
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
|
async def test_get_rooms_database_error(
|
|
async_session: AsyncSession, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test handling of database errors in get_rooms.
|
|
|
|
Verifies that get_rooms raises an exception on database failure.
|
|
"""
|
|
async_session.scalars = AsyncMock(side_effect=SQLAlchemyError("Database error"))
|
|
|
|
with pytest.raises(SQLAlchemyError):
|
|
await get_rooms(async_session)
|
|
async_session.scalars.assert_called_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
|
@pytest.mark.parametrize(
|
|
"room_id, expected_name",
|
|
[
|
|
(1, "Room A"),
|
|
(2, "Room B"),
|
|
],
|
|
ids=["room1", "room2"],
|
|
)
|
|
async def test_get_room_success(
|
|
async_session: AsyncSession,
|
|
room_id: int,
|
|
expected_name: str,
|
|
mock_logger: MagicMock,
|
|
) -> None:
|
|
"""Test successful retrieval of a room by ID.
|
|
|
|
Verifies that get_room returns the correct room and constructs the correct query.
|
|
"""
|
|
room = Room(
|
|
id=room_id,
|
|
name=expected_name,
|
|
location="Building 1",
|
|
equipment="Projector",
|
|
capacity=10,
|
|
)
|
|
async_session.scalar = AsyncMock(return_value=room)
|
|
|
|
result: Room = await get_room(async_session, room_id)
|
|
|
|
assert result.id == room_id
|
|
assert result.name == expected_name
|
|
async_session.scalar.assert_called_once()
|
|
assert async_session.scalar.call_args.args[0].compare(
|
|
select(Room).where(Room.id == room_id)
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
|
@pytest.mark.parametrize(
|
|
"room_id",
|
|
[999, -1],
|
|
ids=["nonexistent_id", "invalid_id"],
|
|
)
|
|
async def test_get_room_not_found(
|
|
async_session: AsyncSession, mock_logger: MagicMock, room_id: int
|
|
) -> None:
|
|
"""Test handling of non-existent room in get_room.
|
|
|
|
Verifies that get_room raises NoResultFound when the room is not found.
|
|
"""
|
|
async_session.scalar = AsyncMock(return_value=None)
|
|
|
|
with pytest.raises(NoResultFound):
|
|
await get_room(async_session, room_id)
|
|
async_session.scalar.assert_called_once()
|
|
assert async_session.scalar.call_args.args[0].compare(
|
|
select(Room).where(Room.id == room_id)
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
|
async def test_get_room_database_error(
|
|
async_session: AsyncSession, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test handling of database errors in get_room.
|
|
|
|
Verifies that get_room raises an exception on database failure.
|
|
"""
|
|
room_id: int = 1
|
|
async_session.scalar = AsyncMock(side_effect=SQLAlchemyError("Database error"))
|
|
|
|
with pytest.raises(SQLAlchemyError):
|
|
await get_room(async_session, room_id)
|
|
async_session.scalar.assert_called_once()
|
|
assert async_session.scalar.call_args.args[0].compare(
|
|
select(Room).where(Room.id == room_id)
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
|
async def test_new_room_success(
|
|
async_session: AsyncSession, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test successful creation of a new room.
|
|
|
|
Verifies that new_room adds the room, commits the session, and returns the room.
|
|
"""
|
|
room = Room(
|
|
id=1, name="Room A", location="Building 1", equipment="Projector", capacity=10
|
|
)
|
|
async_session.add = MagicMock()
|
|
async_session.commit = AsyncMock()
|
|
|
|
result: Room = await new_room(async_session, room)
|
|
|
|
assert result == room
|
|
async_session.add.assert_called_once_with(room)
|
|
async_session.commit.assert_called_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
|
async def test_new_room_database_error(
|
|
async_session: AsyncSession, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test handling of database errors in new_room.
|
|
|
|
Verifies that new_room rolls back the session on database failure.
|
|
"""
|
|
room = Room(
|
|
id=1, name="Room A", location="Building 1", equipment="Projector", capacity=10
|
|
)
|
|
async_session.add = MagicMock()
|
|
async_session.commit = AsyncMock(side_effect=SQLAlchemyError("Database error"))
|
|
async_session.rollback = AsyncMock()
|
|
|
|
with pytest.raises(SQLAlchemyError):
|
|
await new_room(async_session, room)
|
|
async_session.add.assert_called_once_with(room)
|
|
async_session.commit.assert_called_once()
|
|
async_session.rollback.assert_called_once()
|
|
async_session.rollback.assert_called_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
|
async def test_update_room_success(
|
|
async_session: AsyncSession, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test successful update of a room.
|
|
|
|
Verifies that update_room updates the room, commits the session, and returns
|
|
the updated room.
|
|
"""
|
|
room_id = 1
|
|
update_params: dict[str, Any] = {
|
|
"name": "Updated Room",
|
|
"location": "Building 2",
|
|
"equipment": "Whiteboard",
|
|
"capacity": 15,
|
|
}
|
|
mock_execute_result = MagicMock(rowcount=1)
|
|
async_session.execute = AsyncMock(return_value=mock_execute_result)
|
|
async_session.commit = AsyncMock()
|
|
updated_room = Room(id=room_id, **update_params)
|
|
async_session.scalar = AsyncMock(return_value=updated_room)
|
|
|
|
result: Room = await update_room(async_session, room_id, **update_params)
|
|
|
|
assert result == updated_room
|
|
async_session.execute.assert_called_once()
|
|
assert async_session.execute.call_args.args[0].compare(
|
|
update(Room).where(Room.id == room_id).values(**update_params)
|
|
)
|
|
async_session.commit.assert_called_once()
|
|
async_session.scalar.assert_called_once()
|
|
assert async_session.scalar.call_args.args[0].compare(
|
|
select(Room).where(Room.id == room_id)
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
|
async def test_update_room_not_found(
|
|
async_session: AsyncSession, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test handling of non-existent room in update_room.
|
|
|
|
Verifies that update_room raises ValueError when the room is not found.
|
|
"""
|
|
room_id = 999
|
|
update_params: dict[str, Any] = {
|
|
"name": "Updated Room",
|
|
"location": "Building 2",
|
|
"equipment": "Whiteboard",
|
|
"capacity": 15,
|
|
}
|
|
mock_execute_result = MagicMock(rowcount=0)
|
|
async_session.execute = AsyncMock(return_value=mock_execute_result)
|
|
async_session.rollback = AsyncMock()
|
|
|
|
with pytest.raises(ValueError):
|
|
await update_room(async_session, room_id, **update_params)
|
|
async_session.execute.assert_called_once()
|
|
assert async_session.execute.call_args.args[0].compare(
|
|
update(Room).where(Room.id == room_id).values(**update_params)
|
|
)
|
|
async_session.rollback.assert_called_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
|
async def test_update_room_database_error(
|
|
async_session: AsyncSession, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test handling of database errors in update_room.
|
|
|
|
Verifies that update_room rolls back the session on database failure.
|
|
"""
|
|
room_id = 1
|
|
update_params: dict[str, Any] = {
|
|
"name": "Updated Room",
|
|
"location": "Building 2",
|
|
"equipment": "Whiteboard",
|
|
"capacity": 15,
|
|
}
|
|
async_session.execute = AsyncMock(side_effect=SQLAlchemyError("Database error"))
|
|
async_session.rollback = AsyncMock()
|
|
|
|
with pytest.raises(SQLAlchemyError):
|
|
await update_room(async_session, room_id, **update_params)
|
|
async_session.execute.assert_called_once()
|
|
assert async_session.execute.call_args.args[0].compare(
|
|
update(Room).where(Room.id == room_id).values(**update_params)
|
|
)
|
|
async_session.rollback.assert_called_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
|
async def test_delete_room_success(
|
|
async_session: AsyncSession, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test successful deletion of a room.
|
|
|
|
Verifies that delete_room deletes the room and commits the session.
|
|
"""
|
|
room_id = 1
|
|
mock_execute_result = MagicMock(rowcount=1)
|
|
async_session.execute = AsyncMock(return_value=mock_execute_result)
|
|
async_session.commit = AsyncMock()
|
|
|
|
await delete_room(async_session, room_id)
|
|
|
|
async_session.execute.assert_called_once()
|
|
assert async_session.execute.call_args.args[0].compare(
|
|
delete(Room).where(Room.id == room_id)
|
|
)
|
|
async_session.commit.assert_called_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
|
async def test_delete_room_not_found(
|
|
async_session: AsyncSession, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test handling of non-existent room in delete_room.
|
|
|
|
Verifies that delete_room raises ValueError when the room is not found.
|
|
"""
|
|
room_id = 999
|
|
mock_execute_result = MagicMock(rowcount=0)
|
|
async_session.execute = AsyncMock(return_value=mock_execute_result)
|
|
async_session.rollback = AsyncMock()
|
|
|
|
with pytest.raises(ValueError):
|
|
await delete_room(async_session, room_id)
|
|
async_session.execute.assert_called_once()
|
|
assert async_session.execute.call_args.args[0].compare(
|
|
delete(Room).where(Room.id == room_id)
|
|
)
|
|
async_session.rollback.assert_called_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@pytest.mark.parametrize("mock_logger", ["backend.services.rooms"], indirect=True)
|
|
async def test_delete_room_database_error(
|
|
async_session: AsyncSession, mock_logger: MagicMock
|
|
) -> None:
|
|
"""Test handling of database errors in delete_room.
|
|
|
|
Verifies that delete_room rolls back the session on database failure.
|
|
"""
|
|
room_id = 1
|
|
async_session.execute = AsyncMock(side_effect=SQLAlchemyError("Database error"))
|
|
async_session.rollback = AsyncMock()
|
|
|
|
with pytest.raises(SQLAlchemyError):
|
|
await delete_room(async_session, room_id)
|
|
async_session.execute.assert_called_once()
|
|
assert async_session.execute.call_args.args[0].compare(
|
|
delete(Room).where(Room.id == room_id)
|
|
)
|
|
async_session.rollback.assert_called_once()
|