refactor: add service layer architecture with Pydantic validation
- Add services layer (PartyService, ScheduleService, ProductService, ServiceCenterService) - Add ServiceProvider for dependency injection - Add Pydantic input validation on all MCP tools - Add thread-safety to TrytonSettings with double-checked locking - Update tests to mock ServiceProvider instead of direct client calls - Add pydantic dependency
This commit is contained in:
@@ -1,48 +1,61 @@
|
||||
import pytest
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import pytest_asyncio
|
||||
from unittest.mock import MagicMock, patch
|
||||
import json
|
||||
|
||||
from tryton_mcp.server import create_customer
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent / "src"))
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_client():
|
||||
return MagicMock()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_service_provider(mock_client):
|
||||
provider_mock = MagicMock()
|
||||
mock_response = MagicMock()
|
||||
mock_response.is_error = False
|
||||
mock_response.data = []
|
||||
|
||||
provider_mock.party.find_by_identifier.return_value = mock_response
|
||||
provider_mock.party.create.return_value = mock_response
|
||||
|
||||
return provider_mock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def server_with_mocks(mock_service_provider):
|
||||
with patch("tryton_mcp.server._service_provider", mock_service_provider):
|
||||
yield mock_service_provider
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
class TestParty:
|
||||
async def test_create_new_customer(self, server_with_mocks):
|
||||
from tryton_mcp.server import create_customer
|
||||
|
||||
async def test_create_new_customer(self, mcp_client, mock_settings):
|
||||
mock_client = mock_settings.get_client.return_value
|
||||
mock_client.call.return_value = [1]
|
||||
server_with_mocks.party.create.return_value.data = [1]
|
||||
|
||||
result = await mcp_client.call_tool(
|
||||
"create_customer",
|
||||
{
|
||||
"name": "Alejandro Zapata",
|
||||
"identifiers": [["create", [{"type": "mobile", "code": "310659595"}]]],
|
||||
},
|
||||
result = create_customer(
|
||||
name="Alejandro Zapata",
|
||||
identifiers=[["create", [{"type": "mobile", "code": "310659595"}]]],
|
||||
)
|
||||
|
||||
assert result.content is not None
|
||||
assert len(result.content) == 1
|
||||
assert result.content[0].text == "[1]"
|
||||
assert result == [1]
|
||||
|
||||
async def test_find_customer(self, mcp_client, mock_settings):
|
||||
async def test_find_customer(self, server_with_mocks):
|
||||
from tryton_mcp.server import find_customer_by_identifier
|
||||
|
||||
expected_return = [
|
||||
{'id': 19, 'party': 44, 'party.': {'name': 'Alejandro Zapata', 'id': 44}}
|
||||
{"id": 19, "party": 44, "party.": {"name": "Alejandro Zapata", "id": 44}}
|
||||
]
|
||||
|
||||
mock_client = mock_settings.get_client.return_value
|
||||
mock_client.call.return_value = expected_return
|
||||
|
||||
result = await mcp_client.call_tool(
|
||||
"find_customer_by_identifier",
|
||||
{
|
||||
"identifier": "310659595"
|
||||
})
|
||||
|
||||
assert result.content is not None
|
||||
assert len(result.content) == 1
|
||||
assert json.loads(result.content[0].text) == expected_return
|
||||
server_with_mocks.party.find_by_identifier.return_value.data = expected_return
|
||||
|
||||
result = find_customer_by_identifier("310659595")
|
||||
|
||||
assert result == expected_return
|
||||
|
||||
Reference in New Issue
Block a user