import json from unittest.mock import AsyncMock, MagicMock, patch import pytest from ingestor.adapters.nats_consumer import NatsWriteConsumer def make_consumer(**kwargs): return NatsWriteConsumer( nats_url='nats://localhost:4222', write_engine=AsyncMock(), logger=MagicMock(), **kwargs, ) @pytest.mark.asyncio async def test_handle_valid_json_dispatches_to_write_engine(): consumer = make_consumer() payload = {'server_id': 'srv1', 'addr': 'ns=2;i=5', 'value': 1.0, 'data_type': 'float'} msg = MagicMock(data=json.dumps(payload).encode()) await consumer._handle(msg) consumer.write_engine.write.assert_awaited_once_with(payload) @pytest.mark.asyncio async def test_handle_invalid_json_drops_message_and_logs_error(): consumer = make_consumer() msg = MagicMock(data=b'not-json') await consumer._handle(msg) consumer.write_engine.write.assert_not_awaited() consumer.logger.error.assert_called_once() @pytest.mark.asyncio async def test_start_subscribes_with_subject_and_queue(): consumer = make_consumer(subject='opc.write', queue='gateway-writers') mock_nc = AsyncMock() mock_nc.subscribe = AsyncMock() with patch('ingestor.adapters.nats_consumer.nats') as mock_nats: mock_nats.connect = AsyncMock(return_value=mock_nc) await consumer.start() mock_nats.connect.assert_awaited_once_with(servers='nats://localhost:4222') mock_nc.subscribe.assert_awaited_once_with( 'opc.write', queue='gateway-writers', cb=consumer._handle ) @pytest.mark.asyncio async def test_stop_before_start_does_not_raise(): consumer = make_consumer() await consumer.stop() # no raise @pytest.mark.asyncio async def test_stop_after_start_drains_and_unsubscribes(): consumer = make_consumer() mock_nc = AsyncMock() mock_sub = AsyncMock() mock_nc.subscribe = AsyncMock(return_value=mock_sub) with patch('ingestor.adapters.nats_consumer.nats') as mock_nats: mock_nats.connect = AsyncMock(return_value=mock_nc) await consumer.start() await consumer.stop() mock_sub.unsubscribe.assert_awaited_once() mock_nc.drain.assert_awaited_once()