import asyncio from typing import Any from unittest.mock import AsyncMock, MagicMock, patch from app.config import ( CDEKDeliveryProviderConfig, DeliveryProvidersConfig, EmailAdapterConfig, ObservabilityConfig, PostgresConfig, Settings, TBankPaymentAuthConfig, TBankPaymentConfig, WaybillEmailSenderConfig, ) from app.workers.waybill_email_sender import _run def _make_settings() -> Settings: return Settings( delivery_providers=DeliveryProvidersConfig( cdek=CDEKDeliveryProviderConfig( base_url="https://api.cdek.test/v2", client_id="id", client_secret="secret", ) ), tbank_payment=TBankPaymentConfig( init_url="https://pay.test/init", notification_url="https://pay.test/notify", success_url="https://pay.test/success", auth=TBankPaymentAuthConfig(terminal_key="t", password="p"), ), postgres=PostgresConfig(dsn="postgresql+asyncpg://u:p@h/db"), observability=ObservabilityConfig( service_name="svc", otlp_endpoint="http://otlp" ), email=EmailAdapterConfig( smtp_host="smtp.test", smtp_port=587, from_address="no-reply@test", ), waybill_email_sender=WaybillEmailSenderConfig( interval_seconds=0.01, batch_size=5 ), business_logic={"provider_price_multiplier": "1.0"}, ) def test_run_exits_when_stop_event_is_set() -> None: settings = _make_settings() http_client_instance = MagicMock() http_client_instance.aclose = AsyncMock() engine_instance = MagicMock() engine_instance.dispose = AsyncMock() run_forever_mock = AsyncMock() with ( patch( "app.workers.waybill_email_sender.httpx.AsyncClient", return_value=http_client_instance, ), patch("app.workers.waybill_email_sender.CDEKAuthClient"), patch("app.workers.waybill_email_sender.CDEKClient"), patch("app.workers.waybill_email_sender.CSEClient"), patch("app.workers.waybill_email_sender.SMTPEmailSender"), patch( "app.workers.waybill_email_sender.create_postgres_engine", return_value=engine_instance, ), patch("app.workers.waybill_email_sender.create_postgres_session_factory"), patch("app.workers.waybill_email_sender.OrderRepository"), patch( "app.workers.waybill_email_sender.WaybillEmailSenderService" ) as service_cls_mock, ): service_instance = MagicMock() service_instance.run_forever = run_forever_mock service_cls_mock.return_value = service_instance async def runner() -> None: stop_event = asyncio.Event() stop_event.set() await asyncio.wait_for(_run(settings, stop_event), timeout=1.0) asyncio.run(runner()) assert run_forever_mock.await_count == 1 call_kwargs: dict[str, Any] = run_forever_mock.await_args.kwargs assert call_kwargs["interval_seconds"] == 0.01 assert http_client_instance.aclose.await_count == 1 assert engine_instance.dispose.await_count == 1