from unittest.mock import AsyncMock, Mock, patch import pytest from database.async_db import AsyncBotDB class TestAsyncBotDB: """Тесты для AsyncBotDB""" @pytest.fixture def mock_factory(self): """Мок для RepositoryFactory""" mock_factory = Mock() mock_factory.audio = Mock() mock_factory.audio.delete_audio_moderate_record = AsyncMock() mock_factory.users = Mock() mock_factory.users.logger = Mock() # Моки для blacklist и blacklist_history mock_factory.blacklist = Mock() mock_factory.blacklist.add_user = AsyncMock() mock_factory.blacklist.remove_user = AsyncMock(return_value=True) mock_factory.blacklist_history = Mock() mock_factory.blacklist_history.add_record_on_ban = AsyncMock() mock_factory.blacklist_history.set_unban_date = AsyncMock(return_value=True) return mock_factory @pytest.fixture def async_bot_db(self, mock_factory): """Экземпляр AsyncBotDB для тестов""" with patch("database.async_db.RepositoryFactory") as mock_factory_class: mock_factory_class.return_value = mock_factory db = AsyncBotDB("test.db") return db @pytest.mark.asyncio async def test_delete_audio_moderate_record(self, async_bot_db, mock_factory): """Тест метода delete_audio_moderate_record""" message_id = 12345 await async_bot_db.delete_audio_moderate_record(message_id) # Проверяем, что метод вызван в репозитории mock_factory.audio.delete_audio_moderate_record.assert_called_once_with( message_id ) @pytest.mark.asyncio async def test_delete_audio_moderate_record_with_different_message_id( self, async_bot_db, mock_factory ): """Тест метода delete_audio_moderate_record с разными message_id""" test_cases = [123, 456, 789, 99999] for message_id in test_cases: await async_bot_db.delete_audio_moderate_record(message_id) mock_factory.audio.delete_audio_moderate_record.assert_called_with( message_id ) # Проверяем, что метод вызван для каждого message_id assert mock_factory.audio.delete_audio_moderate_record.call_count == len( test_cases ) @pytest.mark.asyncio async def test_delete_audio_moderate_record_exception_handling( self, async_bot_db, mock_factory ): """Тест обработки исключений в delete_audio_moderate_record""" message_id = 12345 mock_factory.audio.delete_audio_moderate_record.side_effect = Exception( "Database error" ) # Метод должен пробросить исключение with pytest.raises(Exception, match="Database error"): await async_bot_db.delete_audio_moderate_record(message_id) @pytest.mark.asyncio async def test_delete_audio_moderate_record_integration_with_other_methods( self, async_bot_db, mock_factory ): """Тест интеграции delete_audio_moderate_record с другими методами""" message_id = 12345 user_id = 67890 # Мокаем другие методы mock_factory.audio.get_user_id_by_message_id_for_voice_bot = AsyncMock( return_value=user_id ) mock_factory.audio.set_user_id_and_message_id_for_voice_bot = AsyncMock( return_value=True ) # Тестируем последовательность операций await async_bot_db.get_user_id_by_message_id_for_voice_bot(message_id) await async_bot_db.set_user_id_and_message_id_for_voice_bot(message_id, user_id) await async_bot_db.delete_audio_moderate_record(message_id) # Проверяем, что все методы вызваны mock_factory.audio.get_user_id_by_message_id_for_voice_bot.assert_called_once_with( message_id ) mock_factory.audio.set_user_id_and_message_id_for_voice_bot.assert_called_once_with( message_id, user_id ) mock_factory.audio.delete_audio_moderate_record.assert_called_once_with( message_id ) @pytest.mark.asyncio async def test_delete_audio_moderate_record_zero_message_id( self, async_bot_db, mock_factory ): """Тест delete_audio_moderate_record с message_id = 0""" message_id = 0 await async_bot_db.delete_audio_moderate_record(message_id) mock_factory.audio.delete_audio_moderate_record.assert_called_once_with( message_id ) @pytest.mark.asyncio async def test_delete_audio_moderate_record_negative_message_id( self, async_bot_db, mock_factory ): """Тест delete_audio_moderate_record с отрицательным message_id""" message_id = -12345 await async_bot_db.delete_audio_moderate_record(message_id) mock_factory.audio.delete_audio_moderate_record.assert_called_once_with( message_id ) @pytest.mark.asyncio async def test_delete_audio_moderate_record_large_message_id( self, async_bot_db, mock_factory ): """Тест delete_audio_moderate_record с большим message_id""" message_id = 999999999 await async_bot_db.delete_audio_moderate_record(message_id) mock_factory.audio.delete_audio_moderate_record.assert_called_once_with( message_id ) @pytest.mark.asyncio async def test_set_user_blacklist_calls_history(self, async_bot_db, mock_factory): """Тест что set_user_blacklist вызывает добавление в историю""" user_id = 12345 message_for_user = "Нарушение правил" date_to_unban = 1234567890 ban_author = 999 await async_bot_db.set_user_blacklist( user_id=user_id, user_name=None, message_for_user=message_for_user, date_to_unban=date_to_unban, ban_author=ban_author, ) # Проверяем, что сначала добавлен в blacklist mock_factory.blacklist.add_user.assert_called_once() # Проверяем, что затем добавлена запись в историю mock_factory.blacklist_history.add_record_on_ban.assert_called_once() # Проверяем параметры записи в историю history_call = mock_factory.blacklist_history.add_record_on_ban.call_args[0][0] assert history_call.user_id == user_id assert history_call.message_for_user == message_for_user assert history_call.date_ban is not None assert history_call.date_unban is None assert history_call.ban_author == ban_author @pytest.mark.asyncio async def test_set_user_blacklist_history_error_does_not_fail( self, async_bot_db, mock_factory ): """Тест что ошибка записи в историю не ломает процесс бана""" user_id = 12345 mock_factory.blacklist_history.add_record_on_ban.side_effect = Exception( "History error" ) # Бан должен пройти успешно, несмотря на ошибку в истории await async_bot_db.set_user_blacklist( user_id=user_id, message_for_user="Тест", date_to_unban=None, ban_author=None, ) # Проверяем, что пользователь все равно добавлен в blacklist mock_factory.blacklist.add_user.assert_called_once() # Проверяем, что попытка записи в историю была mock_factory.blacklist_history.add_record_on_ban.assert_called_once() @pytest.mark.asyncio async def test_delete_user_blacklist_calls_history( self, async_bot_db, mock_factory ): """Тест что delete_user_blacklist вызывает обновление истории""" user_id = 12345 result = await async_bot_db.delete_user_blacklist(user_id) # Проверяем, что сначала обновлена история mock_factory.blacklist_history.set_unban_date.assert_called_once() history_call = mock_factory.blacklist_history.set_unban_date.call_args assert history_call[0][0] == user_id assert history_call[0][1] is not None # date_unban timestamp # Проверяем, что затем удален из blacklist mock_factory.blacklist.remove_user.assert_called_once_with(user_id) # Проверяем результат assert result is True @pytest.mark.asyncio async def test_delete_user_blacklist_history_error_does_not_fail( self, async_bot_db, mock_factory ): """Тест что ошибка обновления истории не ломает процесс разбана""" user_id = 12345 mock_factory.blacklist_history.set_unban_date.side_effect = Exception( "History error" ) # Разбан должен пройти успешно, несмотря на ошибку в истории result = await async_bot_db.delete_user_blacklist(user_id) # Проверяем, что попытка обновления истории была mock_factory.blacklist_history.set_unban_date.assert_called_once() # Проверяем, что пользователь все равно удален из blacklist mock_factory.blacklist.remove_user.assert_called_once_with(user_id) # Проверяем результат assert result is True @pytest.mark.asyncio async def test_delete_user_blacklist_returns_false_on_blacklist_error( self, async_bot_db, mock_factory ): """Тест что delete_user_blacklist возвращает False при ошибке удаления из blacklist""" user_id = 12345 mock_factory.blacklist.remove_user.return_value = False result = await async_bot_db.delete_user_blacklist(user_id) # Проверяем, что история обновлена mock_factory.blacklist_history.set_unban_date.assert_called_once() # Проверяем, что удаление из blacklist было попытка mock_factory.blacklist.remove_user.assert_called_once_with(user_id) # Проверяем результат assert result is False