Fix tests (#593)

* Fix unit/integration/contract tests which were broken by messaging fabric work
This commit is contained in:
cybermaggedon 2025-12-19 08:53:21 +00:00 committed by GitHub
parent 34eb083836
commit 5304f96fe6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 461 additions and 439 deletions

View file

@ -22,18 +22,18 @@ class TestConfigReceiver:
def test_config_receiver_initialization(self):
"""Test ConfigReceiver initialization"""
mock_pulsar_client = Mock()
mock_backend = Mock()
config_receiver = ConfigReceiver(mock_pulsar_client)
config_receiver = ConfigReceiver(mock_backend)
assert config_receiver.pulsar_client == mock_pulsar_client
assert config_receiver.backend == mock_backend
assert config_receiver.flow_handlers == []
assert config_receiver.flows == {}
def test_add_handler(self):
"""Test adding flow handlers"""
mock_pulsar_client = Mock()
config_receiver = ConfigReceiver(mock_pulsar_client)
mock_backend = Mock()
config_receiver = ConfigReceiver(mock_backend)
handler1 = Mock()
handler2 = Mock()
@ -48,8 +48,8 @@ class TestConfigReceiver:
@pytest.mark.asyncio
async def test_on_config_with_new_flows(self):
"""Test on_config method with new flows"""
mock_pulsar_client = Mock()
config_receiver = ConfigReceiver(mock_pulsar_client)
mock_backend = Mock()
config_receiver = ConfigReceiver(mock_backend)
# Track calls manually instead of using AsyncMock
start_flow_calls = []
@ -87,8 +87,8 @@ class TestConfigReceiver:
@pytest.mark.asyncio
async def test_on_config_with_removed_flows(self):
"""Test on_config method with removed flows"""
mock_pulsar_client = Mock()
config_receiver = ConfigReceiver(mock_pulsar_client)
mock_backend = Mock()
config_receiver = ConfigReceiver(mock_backend)
# Pre-populate with existing flows
config_receiver.flows = {
@ -128,8 +128,8 @@ class TestConfigReceiver:
@pytest.mark.asyncio
async def test_on_config_with_no_flows(self):
"""Test on_config method with no flows in config"""
mock_pulsar_client = Mock()
config_receiver = ConfigReceiver(mock_pulsar_client)
mock_backend = Mock()
config_receiver = ConfigReceiver(mock_backend)
# Mock the start_flow and stop_flow methods with async functions
async def mock_start_flow(*args):
@ -158,8 +158,8 @@ class TestConfigReceiver:
@pytest.mark.asyncio
async def test_on_config_exception_handling(self):
"""Test on_config method handles exceptions gracefully"""
mock_pulsar_client = Mock()
config_receiver = ConfigReceiver(mock_pulsar_client)
mock_backend = Mock()
config_receiver = ConfigReceiver(mock_backend)
# Create mock message that will cause an exception
mock_msg = Mock()
@ -174,8 +174,8 @@ class TestConfigReceiver:
@pytest.mark.asyncio
async def test_start_flow_with_handlers(self):
"""Test start_flow method with multiple handlers"""
mock_pulsar_client = Mock()
config_receiver = ConfigReceiver(mock_pulsar_client)
mock_backend = Mock()
config_receiver = ConfigReceiver(mock_backend)
# Add mock handlers
handler1 = Mock()
@ -197,8 +197,8 @@ class TestConfigReceiver:
@pytest.mark.asyncio
async def test_start_flow_with_handler_exception(self):
"""Test start_flow method handles handler exceptions"""
mock_pulsar_client = Mock()
config_receiver = ConfigReceiver(mock_pulsar_client)
mock_backend = Mock()
config_receiver = ConfigReceiver(mock_backend)
# Add mock handler that raises exception
handler = Mock()
@ -217,8 +217,8 @@ class TestConfigReceiver:
@pytest.mark.asyncio
async def test_stop_flow_with_handlers(self):
"""Test stop_flow method with multiple handlers"""
mock_pulsar_client = Mock()
config_receiver = ConfigReceiver(mock_pulsar_client)
mock_backend = Mock()
config_receiver = ConfigReceiver(mock_backend)
# Add mock handlers
handler1 = Mock()
@ -240,8 +240,8 @@ class TestConfigReceiver:
@pytest.mark.asyncio
async def test_stop_flow_with_handler_exception(self):
"""Test stop_flow method handles handler exceptions"""
mock_pulsar_client = Mock()
config_receiver = ConfigReceiver(mock_pulsar_client)
mock_backend = Mock()
config_receiver = ConfigReceiver(mock_backend)
# Add mock handler that raises exception
handler = Mock()
@ -260,9 +260,9 @@ class TestConfigReceiver:
@pytest.mark.asyncio
async def test_config_loader_creates_consumer(self):
"""Test config_loader method creates Pulsar consumer"""
mock_pulsar_client = Mock()
mock_backend = Mock()
config_receiver = ConfigReceiver(mock_pulsar_client)
config_receiver = ConfigReceiver(mock_backend)
# Temporarily restore the real config_loader for this test
config_receiver.config_loader = _real_config_loader.__get__(config_receiver)
@ -291,8 +291,8 @@ class TestConfigReceiver:
# Verify Consumer was created with correct parameters
mock_consumer_class.assert_called_once()
call_args = mock_consumer_class.call_args
assert call_args[1]['client'] == mock_pulsar_client
assert call_args[1]['backend'] == mock_backend
assert call_args[1]['subscriber'] == "gateway-test-uuid"
assert call_args[1]['handler'] == config_receiver.on_config
assert call_args[1]['start_of_messages'] is True
@ -301,8 +301,8 @@ class TestConfigReceiver:
@pytest.mark.asyncio
async def test_start_creates_config_loader_task(self, mock_create_task):
"""Test start method creates config loader task"""
mock_pulsar_client = Mock()
config_receiver = ConfigReceiver(mock_pulsar_client)
mock_backend = Mock()
config_receiver = ConfigReceiver(mock_backend)
# Mock create_task to avoid actually creating tasks with real coroutines
mock_task = Mock()
@ -320,8 +320,8 @@ class TestConfigReceiver:
@pytest.mark.asyncio
async def test_on_config_mixed_flow_operations(self):
"""Test on_config with mixed add/remove operations"""
mock_pulsar_client = Mock()
config_receiver = ConfigReceiver(mock_pulsar_client)
mock_backend = Mock()
config_receiver = ConfigReceiver(mock_backend)
# Pre-populate with existing flows
config_receiver.flows = {
@ -380,8 +380,8 @@ class TestConfigReceiver:
@pytest.mark.asyncio
async def test_on_config_invalid_json_flow_data(self):
"""Test on_config handles invalid JSON in flow data"""
mock_pulsar_client = Mock()
config_receiver = ConfigReceiver(mock_pulsar_client)
mock_backend = Mock()
config_receiver = ConfigReceiver(mock_backend)
# Mock the start_flow method with an async function
async def mock_start_flow(*args):

View file

@ -24,10 +24,10 @@ class TestConfigRequestor:
mock_translator_registry.get_response_translator.return_value = mock_response_translator
# Mock dependencies
mock_pulsar_client = Mock()
mock_backend = Mock()
requestor = ConfigRequestor(
pulsar_client=mock_pulsar_client,
backend=mock_backend,
consumer="test-consumer",
subscriber="test-subscriber",
timeout=60
@ -55,7 +55,7 @@ class TestConfigRequestor:
with patch.object(ServiceRequestor, 'start', return_value=None), \
patch.object(ServiceRequestor, 'process', return_value=None):
requestor = ConfigRequestor(
pulsar_client=Mock(),
backend=Mock(),
consumer="test-consumer",
subscriber="test-subscriber"
)
@ -79,7 +79,7 @@ class TestConfigRequestor:
mock_response_translator.from_response_with_completion.return_value = "translated_response"
requestor = ConfigRequestor(
pulsar_client=Mock(),
backend=Mock(),
consumer="test-consumer",
subscriber="test-subscriber"
)

View file

@ -39,12 +39,12 @@ class TestDispatcherManager:
def test_dispatcher_manager_initialization(self):
"""Test DispatcherManager initialization"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
assert manager.pulsar_client == mock_pulsar_client
assert manager.backend == mock_backend
assert manager.config_receiver == mock_config_receiver
assert manager.prefix == "api-gateway" # default prefix
assert manager.flows == {}
@ -55,19 +55,19 @@ class TestDispatcherManager:
def test_dispatcher_manager_initialization_with_custom_prefix(self):
"""Test DispatcherManager initialization with custom prefix"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver, prefix="custom-prefix")
manager = DispatcherManager(mock_backend, mock_config_receiver, prefix="custom-prefix")
assert manager.prefix == "custom-prefix"
@pytest.mark.asyncio
async def test_start_flow(self):
"""Test start_flow method"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
flow_data = {"name": "test_flow", "steps": []}
@ -79,9 +79,9 @@ class TestDispatcherManager:
@pytest.mark.asyncio
async def test_stop_flow(self):
"""Test stop_flow method"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
# Pre-populate with a flow
flow_data = {"name": "test_flow", "steps": []}
@ -93,9 +93,9 @@ class TestDispatcherManager:
def test_dispatch_global_service_returns_wrapper(self):
"""Test dispatch_global_service returns DispatcherWrapper"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
wrapper = manager.dispatch_global_service()
@ -104,9 +104,9 @@ class TestDispatcherManager:
def test_dispatch_core_export_returns_wrapper(self):
"""Test dispatch_core_export returns DispatcherWrapper"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
wrapper = manager.dispatch_core_export()
@ -115,9 +115,9 @@ class TestDispatcherManager:
def test_dispatch_core_import_returns_wrapper(self):
"""Test dispatch_core_import returns DispatcherWrapper"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
wrapper = manager.dispatch_core_import()
@ -127,9 +127,9 @@ class TestDispatcherManager:
@pytest.mark.asyncio
async def test_process_core_import(self):
"""Test process_core_import method"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
with patch('trustgraph.gateway.dispatch.manager.CoreImport') as mock_core_import:
mock_importer = Mock()
@ -138,16 +138,16 @@ class TestDispatcherManager:
result = await manager.process_core_import("data", "error", "ok", "request")
mock_core_import.assert_called_once_with(mock_pulsar_client)
mock_core_import.assert_called_once_with(mock_backend)
mock_importer.process.assert_called_once_with("data", "error", "ok", "request")
assert result == "import_result"
@pytest.mark.asyncio
async def test_process_core_export(self):
"""Test process_core_export method"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
with patch('trustgraph.gateway.dispatch.manager.CoreExport') as mock_core_export:
mock_exporter = Mock()
@ -156,16 +156,16 @@ class TestDispatcherManager:
result = await manager.process_core_export("data", "error", "ok", "request")
mock_core_export.assert_called_once_with(mock_pulsar_client)
mock_core_export.assert_called_once_with(mock_backend)
mock_exporter.process.assert_called_once_with("data", "error", "ok", "request")
assert result == "export_result"
@pytest.mark.asyncio
async def test_process_global_service(self):
"""Test process_global_service method"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
manager.invoke_global_service = AsyncMock(return_value="global_result")
@ -178,9 +178,9 @@ class TestDispatcherManager:
@pytest.mark.asyncio
async def test_invoke_global_service_with_existing_dispatcher(self):
"""Test invoke_global_service with existing dispatcher"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
# Pre-populate with existing dispatcher
mock_dispatcher = Mock()
@ -195,9 +195,9 @@ class TestDispatcherManager:
@pytest.mark.asyncio
async def test_invoke_global_service_creates_new_dispatcher(self):
"""Test invoke_global_service creates new dispatcher"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
with patch('trustgraph.gateway.dispatch.manager.global_dispatchers') as mock_dispatchers:
mock_dispatcher_class = Mock()
@ -211,7 +211,7 @@ class TestDispatcherManager:
# Verify dispatcher was created with correct parameters
mock_dispatcher_class.assert_called_once_with(
pulsar_client=mock_pulsar_client,
backend=mock_backend,
timeout=120,
consumer="api-gateway-config-request",
subscriber="api-gateway-config-request",
@ -227,9 +227,9 @@ class TestDispatcherManager:
def test_dispatch_flow_import_returns_method(self):
"""Test dispatch_flow_import returns correct method"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
result = manager.dispatch_flow_import()
@ -237,9 +237,9 @@ class TestDispatcherManager:
def test_dispatch_flow_export_returns_method(self):
"""Test dispatch_flow_export returns correct method"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
result = manager.dispatch_flow_export()
@ -247,9 +247,9 @@ class TestDispatcherManager:
def test_dispatch_socket_returns_method(self):
"""Test dispatch_socket returns correct method"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
result = manager.dispatch_socket()
@ -257,9 +257,9 @@ class TestDispatcherManager:
def test_dispatch_flow_service_returns_wrapper(self):
"""Test dispatch_flow_service returns DispatcherWrapper"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
wrapper = manager.dispatch_flow_service()
@ -269,9 +269,9 @@ class TestDispatcherManager:
@pytest.mark.asyncio
async def test_process_flow_import_with_valid_flow_and_kind(self):
"""Test process_flow_import with valid flow and kind"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
# Setup test flow
manager.flows["test_flow"] = {
@ -294,7 +294,7 @@ class TestDispatcherManager:
result = await manager.process_flow_import("ws", "running", params)
mock_dispatcher_class.assert_called_once_with(
pulsar_client=mock_pulsar_client,
backend=mock_backend,
ws="ws",
running="running",
queue={"queue": "test_queue"}
@ -305,9 +305,9 @@ class TestDispatcherManager:
@pytest.mark.asyncio
async def test_process_flow_import_with_invalid_flow(self):
"""Test process_flow_import with invalid flow"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
params = {"flow": "invalid_flow", "kind": "triples"}
@ -320,9 +320,9 @@ class TestDispatcherManager:
import warnings
with warnings.catch_warnings():
warnings.simplefilter("ignore", RuntimeWarning)
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
# Setup test flow
manager.flows["test_flow"] = {
@ -342,9 +342,9 @@ class TestDispatcherManager:
@pytest.mark.asyncio
async def test_process_flow_export_with_valid_flow_and_kind(self):
"""Test process_flow_export with valid flow and kind"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
# Setup test flow
manager.flows["test_flow"] = {
@ -366,7 +366,7 @@ class TestDispatcherManager:
result = await manager.process_flow_export("ws", "running", params)
mock_dispatcher_class.assert_called_once_with(
pulsar_client=mock_pulsar_client,
backend=mock_backend,
ws="ws",
running="running",
queue={"queue": "test_queue"},
@ -378,9 +378,9 @@ class TestDispatcherManager:
@pytest.mark.asyncio
async def test_process_socket(self):
"""Test process_socket method"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
with patch('trustgraph.gateway.dispatch.manager.Mux') as mock_mux:
mock_mux_instance = Mock()
@ -394,9 +394,9 @@ class TestDispatcherManager:
@pytest.mark.asyncio
async def test_process_flow_service(self):
"""Test process_flow_service method"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
manager.invoke_flow_service = AsyncMock(return_value="flow_result")
@ -409,9 +409,9 @@ class TestDispatcherManager:
@pytest.mark.asyncio
async def test_invoke_flow_service_with_existing_dispatcher(self):
"""Test invoke_flow_service with existing dispatcher"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
# Add flow to the flows dictionary
manager.flows["test_flow"] = {"services": {"agent": {}}}
@ -429,9 +429,9 @@ class TestDispatcherManager:
@pytest.mark.asyncio
async def test_invoke_flow_service_creates_request_response_dispatcher(self):
"""Test invoke_flow_service creates request-response dispatcher"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
# Setup test flow
manager.flows["test_flow"] = {
@ -456,7 +456,7 @@ class TestDispatcherManager:
# Verify dispatcher was created with correct parameters
mock_dispatcher_class.assert_called_once_with(
pulsar_client=mock_pulsar_client,
backend=mock_backend,
request_queue="agent_request_queue",
response_queue="agent_response_queue",
timeout=120,
@ -473,9 +473,9 @@ class TestDispatcherManager:
@pytest.mark.asyncio
async def test_invoke_flow_service_creates_sender_dispatcher(self):
"""Test invoke_flow_service creates sender dispatcher"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
# Setup test flow
manager.flows["test_flow"] = {
@ -500,7 +500,7 @@ class TestDispatcherManager:
# Verify dispatcher was created with correct parameters
mock_dispatcher_class.assert_called_once_with(
pulsar_client=mock_pulsar_client,
backend=mock_backend,
queue={"queue": "text_load_queue"}
)
mock_dispatcher.start.assert_called_once()
@ -513,9 +513,9 @@ class TestDispatcherManager:
@pytest.mark.asyncio
async def test_invoke_flow_service_invalid_flow(self):
"""Test invoke_flow_service with invalid flow"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
with pytest.raises(RuntimeError, match="Invalid flow"):
await manager.invoke_flow_service("data", "responder", "invalid_flow", "agent")
@ -523,9 +523,9 @@ class TestDispatcherManager:
@pytest.mark.asyncio
async def test_invoke_flow_service_unsupported_kind_by_flow(self):
"""Test invoke_flow_service with kind not supported by flow"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
# Setup test flow without agent interface
manager.flows["test_flow"] = {
@ -540,9 +540,9 @@ class TestDispatcherManager:
@pytest.mark.asyncio
async def test_invoke_flow_service_invalid_kind(self):
"""Test invoke_flow_service with invalid kind"""
mock_pulsar_client = Mock()
mock_backend = Mock()
mock_config_receiver = Mock()
manager = DispatcherManager(mock_pulsar_client, mock_config_receiver)
manager = DispatcherManager(mock_backend, mock_config_receiver)
# Setup test flow with interface but unsupported kind
manager.flows["test_flow"] = {

View file

@ -15,12 +15,12 @@ class TestServiceRequestor:
@patch('trustgraph.gateway.dispatch.requestor.Subscriber')
def test_service_requestor_initialization(self, mock_subscriber, mock_publisher):
"""Test ServiceRequestor initialization"""
mock_pulsar_client = MagicMock()
mock_backend = MagicMock()
mock_request_schema = MagicMock()
mock_response_schema = MagicMock()
requestor = ServiceRequestor(
pulsar_client=mock_pulsar_client,
backend=mock_backend,
request_queue="test-request-queue",
request_schema=mock_request_schema,
response_queue="test-response-queue",
@ -32,12 +32,12 @@ class TestServiceRequestor:
# Verify Publisher was created correctly
mock_publisher.assert_called_once_with(
mock_pulsar_client, "test-request-queue", schema=mock_request_schema
mock_backend, "test-request-queue", schema=mock_request_schema
)
# Verify Subscriber was created correctly
mock_subscriber.assert_called_once_with(
mock_pulsar_client, "test-response-queue",
mock_backend, "test-response-queue",
"test-subscription", "test-consumer", mock_response_schema
)
@ -48,12 +48,12 @@ class TestServiceRequestor:
@patch('trustgraph.gateway.dispatch.requestor.Subscriber')
def test_service_requestor_with_defaults(self, mock_subscriber, mock_publisher):
"""Test ServiceRequestor initialization with default parameters"""
mock_pulsar_client = MagicMock()
mock_backend = MagicMock()
mock_request_schema = MagicMock()
mock_response_schema = MagicMock()
requestor = ServiceRequestor(
pulsar_client=mock_pulsar_client,
backend=mock_backend,
request_queue="test-queue",
request_schema=mock_request_schema,
response_queue="response-queue",
@ -62,7 +62,7 @@ class TestServiceRequestor:
# Verify default values
mock_subscriber.assert_called_once_with(
mock_pulsar_client, "response-queue",
mock_backend, "response-queue",
"api-gateway", "api-gateway", mock_response_schema
)
assert requestor.timeout == 600 # Default timeout
@ -72,14 +72,14 @@ class TestServiceRequestor:
@pytest.mark.asyncio
async def test_service_requestor_start(self, mock_subscriber, mock_publisher):
"""Test ServiceRequestor start method"""
mock_pulsar_client = MagicMock()
mock_backend = MagicMock()
mock_sub_instance = AsyncMock()
mock_pub_instance = AsyncMock()
mock_subscriber.return_value = mock_sub_instance
mock_publisher.return_value = mock_pub_instance
requestor = ServiceRequestor(
pulsar_client=mock_pulsar_client,
backend=mock_backend,
request_queue="test-queue",
request_schema=MagicMock(),
response_queue="response-queue",
@ -98,14 +98,14 @@ class TestServiceRequestor:
@patch('trustgraph.gateway.dispatch.requestor.Subscriber')
def test_service_requestor_attributes(self, mock_subscriber, mock_publisher):
"""Test ServiceRequestor has correct attributes"""
mock_pulsar_client = MagicMock()
mock_backend = MagicMock()
mock_pub_instance = AsyncMock()
mock_sub_instance = AsyncMock()
mock_publisher.return_value = mock_pub_instance
mock_subscriber.return_value = mock_sub_instance
requestor = ServiceRequestor(
pulsar_client=mock_pulsar_client,
backend=mock_backend,
request_queue="test-queue",
request_schema=MagicMock(),
response_queue="response-queue",

View file

@ -14,18 +14,18 @@ class TestServiceSender:
@patch('trustgraph.gateway.dispatch.sender.Publisher')
def test_service_sender_initialization(self, mock_publisher):
"""Test ServiceSender initialization"""
mock_pulsar_client = MagicMock()
mock_backend = MagicMock()
mock_schema = MagicMock()
sender = ServiceSender(
pulsar_client=mock_pulsar_client,
backend=mock_backend,
queue="test-queue",
schema=mock_schema
)
# Verify Publisher was created correctly
mock_publisher.assert_called_once_with(
mock_pulsar_client, "test-queue", schema=mock_schema
mock_backend, "test-queue", schema=mock_schema
)
@patch('trustgraph.gateway.dispatch.sender.Publisher')
@ -36,7 +36,7 @@ class TestServiceSender:
mock_publisher.return_value = mock_pub_instance
sender = ServiceSender(
pulsar_client=MagicMock(),
backend=MagicMock(),
queue="test-queue",
schema=MagicMock()
)
@ -55,7 +55,7 @@ class TestServiceSender:
mock_publisher.return_value = mock_pub_instance
sender = ServiceSender(
pulsar_client=MagicMock(),
backend=MagicMock(),
queue="test-queue",
schema=MagicMock()
)
@ -70,7 +70,7 @@ class TestServiceSender:
def test_service_sender_to_request_not_implemented(self, mock_publisher):
"""Test ServiceSender to_request method raises RuntimeError"""
sender = ServiceSender(
pulsar_client=MagicMock(),
backend=MagicMock(),
queue="test-queue",
schema=MagicMock()
)
@ -91,7 +91,7 @@ class TestServiceSender:
return {"processed": request}
sender = ConcreteSender(
pulsar_client=MagicMock(),
backend=MagicMock(),
queue="test-queue",
schema=MagicMock()
)
@ -111,7 +111,7 @@ class TestServiceSender:
mock_publisher.return_value = mock_pub_instance
sender = ServiceSender(
pulsar_client=MagicMock(),
backend=MagicMock(),
queue="test-queue",
schema=MagicMock()
)

View file

@ -16,7 +16,7 @@ from trustgraph.schema import Metadata, ExtractedObject
@pytest.fixture
def mock_pulsar_client():
def mock_backend():
"""Mock Pulsar client."""
client = Mock()
return client
@ -96,7 +96,7 @@ class TestObjectsImportInitialization:
"""Test ObjectsImport initialization."""
@patch('trustgraph.gateway.dispatch.objects_import.Publisher')
def test_init_creates_publisher_with_correct_params(self, mock_publisher_class, mock_pulsar_client, mock_websocket, mock_running):
def test_init_creates_publisher_with_correct_params(self, mock_publisher_class, mock_backend, mock_websocket, mock_running):
"""Test that ObjectsImport creates Publisher with correct parameters."""
mock_publisher_instance = Mock()
mock_publisher_class.return_value = mock_publisher_instance
@ -104,13 +104,13 @@ class TestObjectsImportInitialization:
objects_import = ObjectsImport(
ws=mock_websocket,
running=mock_running,
pulsar_client=mock_pulsar_client,
backend=mock_backend,
queue="test-objects-queue"
)
# Verify Publisher was created with correct parameters
mock_publisher_class.assert_called_once_with(
mock_pulsar_client,
mock_backend,
topic="test-objects-queue",
schema=ExtractedObject
)
@ -121,12 +121,12 @@ class TestObjectsImportInitialization:
assert objects_import.publisher == mock_publisher_instance
@patch('trustgraph.gateway.dispatch.objects_import.Publisher')
def test_init_stores_references_correctly(self, mock_publisher_class, mock_pulsar_client, mock_websocket, mock_running):
def test_init_stores_references_correctly(self, mock_publisher_class, mock_backend, mock_websocket, mock_running):
"""Test that ObjectsImport stores all required references."""
objects_import = ObjectsImport(
ws=mock_websocket,
running=mock_running,
pulsar_client=mock_pulsar_client,
backend=mock_backend,
queue="objects-queue"
)
@ -139,7 +139,7 @@ class TestObjectsImportLifecycle:
@patch('trustgraph.gateway.dispatch.objects_import.Publisher')
@pytest.mark.asyncio
async def test_start_calls_publisher_start(self, mock_publisher_class, mock_pulsar_client, mock_websocket, mock_running):
async def test_start_calls_publisher_start(self, mock_publisher_class, mock_backend, mock_websocket, mock_running):
"""Test that start() calls publisher.start()."""
mock_publisher_instance = Mock()
mock_publisher_instance.start = AsyncMock()
@ -148,7 +148,7 @@ class TestObjectsImportLifecycle:
objects_import = ObjectsImport(
ws=mock_websocket,
running=mock_running,
pulsar_client=mock_pulsar_client,
backend=mock_backend,
queue="test-queue"
)
@ -158,7 +158,7 @@ class TestObjectsImportLifecycle:
@patch('trustgraph.gateway.dispatch.objects_import.Publisher')
@pytest.mark.asyncio
async def test_destroy_stops_and_closes_properly(self, mock_publisher_class, mock_pulsar_client, mock_websocket, mock_running):
async def test_destroy_stops_and_closes_properly(self, mock_publisher_class, mock_backend, mock_websocket, mock_running):
"""Test that destroy() properly stops publisher and closes websocket."""
mock_publisher_instance = Mock()
mock_publisher_instance.stop = AsyncMock()
@ -167,7 +167,7 @@ class TestObjectsImportLifecycle:
objects_import = ObjectsImport(
ws=mock_websocket,
running=mock_running,
pulsar_client=mock_pulsar_client,
backend=mock_backend,
queue="test-queue"
)
@ -180,7 +180,7 @@ class TestObjectsImportLifecycle:
@patch('trustgraph.gateway.dispatch.objects_import.Publisher')
@pytest.mark.asyncio
async def test_destroy_handles_none_websocket(self, mock_publisher_class, mock_pulsar_client, mock_running):
async def test_destroy_handles_none_websocket(self, mock_publisher_class, mock_backend, mock_running):
"""Test that destroy() handles None websocket gracefully."""
mock_publisher_instance = Mock()
mock_publisher_instance.stop = AsyncMock()
@ -189,7 +189,7 @@ class TestObjectsImportLifecycle:
objects_import = ObjectsImport(
ws=None, # None websocket
running=mock_running,
pulsar_client=mock_pulsar_client,
backend=mock_backend,
queue="test-queue"
)
@ -205,7 +205,7 @@ class TestObjectsImportMessageProcessing:
@patch('trustgraph.gateway.dispatch.objects_import.Publisher')
@pytest.mark.asyncio
async def test_receive_processes_full_message_correctly(self, mock_publisher_class, mock_pulsar_client, mock_websocket, mock_running, sample_objects_message):
async def test_receive_processes_full_message_correctly(self, mock_publisher_class, mock_backend, mock_websocket, mock_running, sample_objects_message):
"""Test that receive() processes complete message correctly."""
mock_publisher_instance = Mock()
mock_publisher_instance.send = AsyncMock()
@ -214,7 +214,7 @@ class TestObjectsImportMessageProcessing:
objects_import = ObjectsImport(
ws=mock_websocket,
running=mock_running,
pulsar_client=mock_pulsar_client,
backend=mock_backend,
queue="test-queue"
)
@ -248,7 +248,7 @@ class TestObjectsImportMessageProcessing:
@patch('trustgraph.gateway.dispatch.objects_import.Publisher')
@pytest.mark.asyncio
async def test_receive_handles_minimal_message(self, mock_publisher_class, mock_pulsar_client, mock_websocket, mock_running, minimal_objects_message):
async def test_receive_handles_minimal_message(self, mock_publisher_class, mock_backend, mock_websocket, mock_running, minimal_objects_message):
"""Test that receive() handles message with minimal required fields."""
mock_publisher_instance = Mock()
mock_publisher_instance.send = AsyncMock()
@ -257,7 +257,7 @@ class TestObjectsImportMessageProcessing:
objects_import = ObjectsImport(
ws=mock_websocket,
running=mock_running,
pulsar_client=mock_pulsar_client,
backend=mock_backend,
queue="test-queue"
)
@ -281,7 +281,7 @@ class TestObjectsImportMessageProcessing:
@patch('trustgraph.gateway.dispatch.objects_import.Publisher')
@pytest.mark.asyncio
async def test_receive_uses_default_values(self, mock_publisher_class, mock_pulsar_client, mock_websocket, mock_running):
async def test_receive_uses_default_values(self, mock_publisher_class, mock_backend, mock_websocket, mock_running):
"""Test that receive() uses appropriate default values for optional fields."""
mock_publisher_instance = Mock()
mock_publisher_instance.send = AsyncMock()
@ -290,7 +290,7 @@ class TestObjectsImportMessageProcessing:
objects_import = ObjectsImport(
ws=mock_websocket,
running=mock_running,
pulsar_client=mock_pulsar_client,
backend=mock_backend,
queue="test-queue"
)
@ -323,7 +323,7 @@ class TestObjectsImportRunMethod:
@patch('trustgraph.gateway.dispatch.objects_import.Publisher')
@patch('trustgraph.gateway.dispatch.objects_import.asyncio.sleep')
@pytest.mark.asyncio
async def test_run_loops_while_running(self, mock_sleep, mock_publisher_class, mock_pulsar_client, mock_websocket, mock_running):
async def test_run_loops_while_running(self, mock_sleep, mock_publisher_class, mock_backend, mock_websocket, mock_running):
"""Test that run() loops while running.get() returns True."""
mock_sleep.return_value = None
mock_publisher_class.return_value = Mock()
@ -334,7 +334,7 @@ class TestObjectsImportRunMethod:
objects_import = ObjectsImport(
ws=mock_websocket,
running=mock_running,
pulsar_client=mock_pulsar_client,
backend=mock_backend,
queue="test-queue"
)
@ -353,7 +353,7 @@ class TestObjectsImportRunMethod:
@patch('trustgraph.gateway.dispatch.objects_import.Publisher')
@patch('trustgraph.gateway.dispatch.objects_import.asyncio.sleep')
@pytest.mark.asyncio
async def test_run_handles_none_websocket_gracefully(self, mock_sleep, mock_publisher_class, mock_pulsar_client, mock_running):
async def test_run_handles_none_websocket_gracefully(self, mock_sleep, mock_publisher_class, mock_backend, mock_running):
"""Test that run() handles None websocket gracefully."""
mock_sleep.return_value = None
mock_publisher_class.return_value = Mock()
@ -363,7 +363,7 @@ class TestObjectsImportRunMethod:
objects_import = ObjectsImport(
ws=None, # None websocket
running=mock_running,
pulsar_client=mock_pulsar_client,
backend=mock_backend,
queue="test-queue"
)
@ -417,7 +417,7 @@ class TestObjectsImportBatchProcessing:
@patch('trustgraph.gateway.dispatch.objects_import.Publisher')
@pytest.mark.asyncio
async def test_receive_processes_batch_message_correctly(self, mock_publisher_class, mock_pulsar_client, mock_websocket, mock_running, batch_objects_message):
async def test_receive_processes_batch_message_correctly(self, mock_publisher_class, mock_backend, mock_websocket, mock_running, batch_objects_message):
"""Test that receive() processes batch message correctly."""
mock_publisher_instance = Mock()
mock_publisher_instance.send = AsyncMock()
@ -426,7 +426,7 @@ class TestObjectsImportBatchProcessing:
objects_import = ObjectsImport(
ws=mock_websocket,
running=mock_running,
pulsar_client=mock_pulsar_client,
backend=mock_backend,
queue="test-queue"
)
@ -467,7 +467,7 @@ class TestObjectsImportBatchProcessing:
@patch('trustgraph.gateway.dispatch.objects_import.Publisher')
@pytest.mark.asyncio
async def test_receive_handles_empty_batch(self, mock_publisher_class, mock_pulsar_client, mock_websocket, mock_running):
async def test_receive_handles_empty_batch(self, mock_publisher_class, mock_backend, mock_websocket, mock_running):
"""Test that receive() handles empty batch correctly."""
mock_publisher_instance = Mock()
mock_publisher_instance.send = AsyncMock()
@ -476,7 +476,7 @@ class TestObjectsImportBatchProcessing:
objects_import = ObjectsImport(
ws=mock_websocket,
running=mock_running,
pulsar_client=mock_pulsar_client,
backend=mock_backend,
queue="test-queue"
)
@ -507,7 +507,7 @@ class TestObjectsImportErrorHandling:
@patch('trustgraph.gateway.dispatch.objects_import.Publisher')
@pytest.mark.asyncio
async def test_receive_propagates_publisher_errors(self, mock_publisher_class, mock_pulsar_client, mock_websocket, mock_running, sample_objects_message):
async def test_receive_propagates_publisher_errors(self, mock_publisher_class, mock_backend, mock_websocket, mock_running, sample_objects_message):
"""Test that receive() propagates publisher send errors."""
mock_publisher_instance = Mock()
mock_publisher_instance.send = AsyncMock(side_effect=Exception("Publisher error"))
@ -516,7 +516,7 @@ class TestObjectsImportErrorHandling:
objects_import = ObjectsImport(
ws=mock_websocket,
running=mock_running,
pulsar_client=mock_pulsar_client,
backend=mock_backend,
queue="test-queue"
)
@ -528,14 +528,14 @@ class TestObjectsImportErrorHandling:
@patch('trustgraph.gateway.dispatch.objects_import.Publisher')
@pytest.mark.asyncio
async def test_receive_handles_malformed_json(self, mock_publisher_class, mock_pulsar_client, mock_websocket, mock_running):
async def test_receive_handles_malformed_json(self, mock_publisher_class, mock_backend, mock_websocket, mock_running):
"""Test that receive() handles malformed JSON appropriately."""
mock_publisher_class.return_value = Mock()
objects_import = ObjectsImport(
ws=mock_websocket,
running=mock_running,
pulsar_client=mock_pulsar_client,
backend=mock_backend,
queue="test-queue"
)

View file

@ -19,23 +19,21 @@ class TestApi:
def test_api_initialization_with_defaults(self):
"""Test Api initialization with default values"""
with patch('pulsar.Client') as mock_client:
mock_client.return_value = Mock()
with patch('trustgraph.gateway.service.get_pubsub') as mock_get_pubsub:
mock_backend = Mock()
mock_get_pubsub.return_value = mock_backend
api = Api()
assert api.port == default_port
assert api.timeout == default_timeout
assert api.pulsar_host == default_pulsar_host
assert api.pulsar_api_key is None
assert api.prometheus_url == default_prometheus_url + "/"
assert api.auth.allow_all is True
# Verify Pulsar client was created without API key
mock_client.assert_called_once_with(
default_pulsar_host,
listener_name=None
)
# Verify get_pubsub was called
mock_get_pubsub.assert_called_once()
def test_api_initialization_with_custom_config(self):
"""Test Api initialization with custom configuration"""
@ -48,14 +46,13 @@ class TestApi:
"prometheus_url": "http://custom-prometheus:9090",
"api_token": "secret-token"
}
with patch('pulsar.Client') as mock_client, \
patch('pulsar.AuthenticationToken') as mock_auth:
mock_client.return_value = Mock()
mock_auth.return_value = Mock()
with patch('trustgraph.gateway.service.get_pubsub') as mock_get_pubsub:
mock_backend = Mock()
mock_get_pubsub.return_value = mock_backend
api = Api(**config)
assert api.port == 9000
assert api.timeout == 300
assert api.pulsar_host == "pulsar://custom-host:6650"
@ -63,35 +60,25 @@ class TestApi:
assert api.prometheus_url == "http://custom-prometheus:9090/"
assert api.auth.token == "secret-token"
assert api.auth.allow_all is False
# Verify Pulsar client was created with API key
mock_auth.assert_called_once_with("test-api-key")
mock_client.assert_called_once_with(
"pulsar://custom-host:6650",
listener_name="custom-listener",
authentication=mock_auth.return_value
)
# Verify get_pubsub was called with config
mock_get_pubsub.assert_called_once_with(**config)
def test_api_initialization_with_pulsar_api_key(self):
"""Test Api initialization with Pulsar API key authentication"""
with patch('pulsar.Client') as mock_client, \
patch('pulsar.AuthenticationToken') as mock_auth:
mock_client.return_value = Mock()
mock_auth.return_value = Mock()
with patch('trustgraph.gateway.service.get_pubsub') as mock_get_pubsub:
mock_get_pubsub.return_value = Mock()
api = Api(pulsar_api_key="test-key")
mock_auth.assert_called_once_with("test-key")
mock_client.assert_called_once_with(
default_pulsar_host,
listener_name=None,
authentication=mock_auth.return_value
)
# Verify api key was stored
assert api.pulsar_api_key == "test-key"
mock_get_pubsub.assert_called_once()
def test_api_initialization_prometheus_url_normalization(self):
"""Test that prometheus_url gets normalized with trailing slash"""
with patch('pulsar.Client') as mock_client:
mock_client.return_value = Mock()
with patch('trustgraph.gateway.service.get_pubsub') as mock_get_pubsub:
mock_get_pubsub.return_value = Mock()
# Test URL without trailing slash
api = Api(prometheus_url="http://prometheus:9090")
@ -103,16 +90,16 @@ class TestApi:
def test_api_initialization_empty_api_token_means_no_auth(self):
"""Test that empty API token results in allow_all authentication"""
with patch('pulsar.Client') as mock_client:
mock_client.return_value = Mock()
with patch('trustgraph.gateway.service.get_pubsub') as mock_get_pubsub:
mock_get_pubsub.return_value = Mock()
api = Api(api_token="")
assert api.auth.allow_all is True
def test_api_initialization_none_api_token_means_no_auth(self):
"""Test that None API token results in allow_all authentication"""
with patch('pulsar.Client') as mock_client:
mock_client.return_value = Mock()
with patch('trustgraph.gateway.service.get_pubsub') as mock_get_pubsub:
mock_get_pubsub.return_value = Mock()
api = Api(api_token=None)
assert api.auth.allow_all is True
@ -120,8 +107,8 @@ class TestApi:
@pytest.mark.asyncio
async def test_app_factory_creates_application(self):
"""Test that app_factory creates aiohttp application"""
with patch('pulsar.Client') as mock_client:
mock_client.return_value = Mock()
with patch('trustgraph.gateway.service.get_pubsub') as mock_get_pubsub:
mock_get_pubsub.return_value = Mock()
api = Api()
@ -147,8 +134,8 @@ class TestApi:
@pytest.mark.asyncio
async def test_app_factory_with_custom_endpoints(self):
"""Test app_factory with custom endpoints"""
with patch('pulsar.Client') as mock_client:
mock_client.return_value = Mock()
with patch('trustgraph.gateway.service.get_pubsub') as mock_get_pubsub:
mock_get_pubsub.return_value = Mock()
api = Api()
@ -180,13 +167,13 @@ class TestApi:
def test_run_method_calls_web_run_app(self):
"""Test that run method calls web.run_app"""
with patch('pulsar.Client') as mock_client, \
with patch('trustgraph.gateway.service.get_pubsub') as mock_get_pubsub, \
patch('aiohttp.web.run_app') as mock_run_app:
mock_client.return_value = Mock()
mock_get_pubsub.return_value = Mock()
api = Api(port=8080)
api.run()
# Verify run_app was called once with the correct port
mock_run_app.assert_called_once()
args, kwargs = mock_run_app.call_args
@ -195,19 +182,19 @@ class TestApi:
def test_api_components_initialization(self):
"""Test that all API components are properly initialized"""
with patch('pulsar.Client') as mock_client:
mock_client.return_value = Mock()
with patch('trustgraph.gateway.service.get_pubsub') as mock_get_pubsub:
mock_get_pubsub.return_value = Mock()
api = Api()
# Verify all components are initialized
assert api.config_receiver is not None
assert api.dispatcher_manager is not None
assert api.endpoint_manager is not None
assert api.endpoints == []
# Verify component relationships
assert api.dispatcher_manager.pulsar_client == api.pulsar_client
assert api.dispatcher_manager.backend == api.pubsub_backend
assert api.dispatcher_manager.config_receiver == api.config_receiver
assert api.endpoint_manager.dispatcher_manager == api.dispatcher_manager
# EndpointManager doesn't store auth directly, it passes it to individual endpoints