218 lines
8.6 KiB
Python
218 lines
8.6 KiB
Python
import asyncio
|
||
from datetime import datetime
|
||
from unittest.mock import AsyncMock, MagicMock
|
||
|
||
import pytest
|
||
|
||
from database.models import UserMessage
|
||
from database.repositories.message_repository import MessageRepository
|
||
|
||
|
||
class TestMessageRepository:
|
||
"""Тесты для MessageRepository."""
|
||
|
||
@pytest.fixture
|
||
def mock_db_path(self):
|
||
"""Фикстура для пути к тестовой БД."""
|
||
return ":memory:"
|
||
|
||
@pytest.fixture
|
||
def message_repository(self, mock_db_path):
|
||
"""Фикстура для MessageRepository."""
|
||
return MessageRepository(mock_db_path)
|
||
|
||
@pytest.fixture
|
||
def sample_message(self):
|
||
"""Фикстура для тестового сообщения."""
|
||
return UserMessage(
|
||
message_text="Тестовое сообщение",
|
||
user_id=12345,
|
||
telegram_message_id=67890,
|
||
date=int(datetime.now().timestamp()),
|
||
)
|
||
|
||
@pytest.fixture
|
||
def sample_message_no_date(self):
|
||
"""Фикстура для тестового сообщения без даты."""
|
||
return UserMessage(
|
||
message_text="Тестовое сообщение без даты",
|
||
user_id=12345,
|
||
telegram_message_id=67891,
|
||
date=None,
|
||
)
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_create_tables(self, message_repository):
|
||
"""Тест создания таблиц."""
|
||
# Мокаем _execute_query
|
||
message_repository._execute_query = AsyncMock()
|
||
|
||
await message_repository.create_tables()
|
||
|
||
message_repository._execute_query.assert_called_once()
|
||
call_args = message_repository._execute_query.call_args[0][0]
|
||
assert "CREATE TABLE IF NOT EXISTS user_messages" in call_args
|
||
assert "telegram_message_id INTEGER NOT NULL" in call_args
|
||
assert "date INTEGER NOT NULL" in call_args
|
||
assert (
|
||
"FOREIGN KEY (user_id) REFERENCES our_users (user_id) ON DELETE CASCADE"
|
||
in call_args
|
||
)
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_add_message_with_date(self, message_repository, sample_message):
|
||
"""Тест добавления сообщения с датой."""
|
||
# Мокаем _execute_query
|
||
message_repository._execute_query = AsyncMock()
|
||
|
||
await message_repository.add_message(sample_message)
|
||
|
||
message_repository._execute_query.assert_called_once()
|
||
call_args = message_repository._execute_query.call_args
|
||
query = call_args[0][0]
|
||
params = call_args[0][1]
|
||
|
||
assert "INSERT INTO user_messages" in query
|
||
assert "VALUES (?, ?, ?, ?)" in query
|
||
assert params == (
|
||
sample_message.message_text,
|
||
sample_message.user_id,
|
||
sample_message.telegram_message_id,
|
||
sample_message.date,
|
||
)
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_add_message_without_date(
|
||
self, message_repository, sample_message_no_date
|
||
):
|
||
"""Тест добавления сообщения без даты (должна генерироваться автоматически)."""
|
||
# Мокаем _execute_query
|
||
message_repository._execute_query = AsyncMock()
|
||
|
||
await message_repository.add_message(sample_message_no_date)
|
||
|
||
# Проверяем, что дата была установлена
|
||
assert sample_message_no_date.date is not None
|
||
assert isinstance(sample_message_no_date.date, int)
|
||
assert sample_message_no_date.date > 0
|
||
|
||
message_repository._execute_query.assert_called_once()
|
||
call_args = message_repository._execute_query.call_args
|
||
params = call_args[0][1]
|
||
|
||
assert params[3] == sample_message_no_date.date # date field
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_add_message_logs_correctly(self, message_repository, sample_message):
|
||
"""Тест логирования при добавлении сообщения."""
|
||
# Мокаем _execute_query и logger
|
||
message_repository._execute_query = AsyncMock()
|
||
message_repository.logger = MagicMock()
|
||
|
||
await message_repository.add_message(sample_message)
|
||
|
||
message_repository.logger.info.assert_called_once()
|
||
log_message = message_repository.logger.info.call_args[0][0]
|
||
assert (
|
||
f"telegram_message_id={sample_message.telegram_message_id}" in log_message
|
||
)
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_get_user_by_message_id_found(self, message_repository):
|
||
"""Тест получения пользователя по message_id (пользователь найден)."""
|
||
message_id = 67890
|
||
expected_user_id = 12345
|
||
|
||
# Мокаем _execute_query_with_result
|
||
message_repository._execute_query_with_result = AsyncMock(
|
||
return_value=[[expected_user_id]]
|
||
)
|
||
|
||
result = await message_repository.get_user_by_message_id(message_id)
|
||
|
||
assert result == expected_user_id
|
||
message_repository._execute_query_with_result.assert_called_once_with(
|
||
"SELECT user_id FROM user_messages WHERE telegram_message_id = ?",
|
||
(message_id,),
|
||
)
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_get_user_by_message_id_not_found(self, message_repository):
|
||
"""Тест получения пользователя по message_id (пользователь не найден)."""
|
||
message_id = 99999
|
||
|
||
# Мокаем _execute_query_with_result
|
||
message_repository._execute_query_with_result = AsyncMock(return_value=[])
|
||
|
||
result = await message_repository.get_user_by_message_id(message_id)
|
||
|
||
assert result is None
|
||
message_repository._execute_query_with_result.assert_called_once_with(
|
||
"SELECT user_id FROM user_messages WHERE telegram_message_id = ?",
|
||
(message_id,),
|
||
)
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_get_user_by_message_id_empty_result(self, message_repository):
|
||
"""Тест получения пользователя по message_id (пустой результат)."""
|
||
message_id = 99999
|
||
|
||
# Мокаем _execute_query_with_result
|
||
message_repository._execute_query_with_result = AsyncMock(return_value=[[]])
|
||
|
||
result = await message_repository.get_user_by_message_id(message_id)
|
||
|
||
assert result is None
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_add_message_handles_exception(
|
||
self, message_repository, sample_message
|
||
):
|
||
"""Тест обработки исключений при добавлении сообщения."""
|
||
# Мокаем _execute_query для вызова исключения
|
||
message_repository._execute_query = AsyncMock(
|
||
side_effect=Exception("Database error")
|
||
)
|
||
|
||
with pytest.raises(Exception, match="Database error"):
|
||
await message_repository.add_message(sample_message)
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_get_user_by_message_id_handles_exception(self, message_repository):
|
||
"""Тест обработки исключений при получении пользователя."""
|
||
# Мокаем _execute_query_with_result для вызова исключения
|
||
message_repository._execute_query_with_result = AsyncMock(
|
||
side_effect=Exception("Database error")
|
||
)
|
||
|
||
with pytest.raises(Exception, match="Database error"):
|
||
await message_repository.get_user_by_message_id(12345)
|
||
|
||
@pytest.mark.asyncio
|
||
async def test_add_message_with_zero_date(self, message_repository):
|
||
"""Тест добавления сообщения с датой равной 0 (должна генерироваться новая)."""
|
||
message = UserMessage(
|
||
message_text="Тестовое сообщение с нулевой датой",
|
||
user_id=12345,
|
||
telegram_message_id=67892,
|
||
date=0,
|
||
)
|
||
|
||
# Мокаем _execute_query
|
||
message_repository._execute_query = AsyncMock()
|
||
|
||
await message_repository.add_message(message)
|
||
|
||
# Проверяем, что дата была изменена с 0 (теперь это происходит только если date is None)
|
||
# В текущей реализации дата 0 считается валидной и не изменяется
|
||
assert isinstance(message.date, int)
|
||
assert message.date >= 0
|
||
|
||
message_repository._execute_query.assert_called_once()
|
||
params = message_repository._execute_query.call_args[0][1]
|
||
assert params[3] == message.date # date field
|
||
|
||
|
||
if __name__ == "__main__":
|
||
pytest.main([__file__])
|