test_server.pyβ’6.54 kB
"""
Unit tests for MCP Stock Details Server
TDD Red Phase: Write failing tests first
"""
import pytest
import asyncio
from unittest.mock import Mock, AsyncMock
# Test imports will fail initially - this is expected in TDD Red phase
try:
from src.server import MCPStockDetailsServer
from src.config import get_settings
from src.exceptions import MCPStockDetailsError, CompanyNotFoundError
except ImportError:
# Expected in Red phase - we haven't implemented these yet
pass
class TestMCPStockDetailsServer:
"""Test cases for MCP Stock Details Server"""
@pytest.fixture
def server(self):
"""Create server instance for testing"""
# This will fail initially - Red phase
return MCPStockDetailsServer()
@pytest.mark.asyncio
async def test_server_initialization(self, server):
"""Test that server initializes correctly"""
assert server is not None
assert hasattr(server, 'name')
assert hasattr(server, 'version')
assert server.name == "mcp-stock-details"
assert server.version == "1.0.0"
@pytest.mark.asyncio
async def test_server_has_required_tools(self, server):
"""Test that server has all required tools registered"""
required_tools = [
"get_company_overview",
"get_financial_statements"
]
tools = await server.list_tools()
tool_names = [tool.name for tool in tools]
for required_tool in required_tools:
assert required_tool in tool_names
@pytest.mark.asyncio
async def test_get_company_overview_tool_exists(self, server):
"""Test that get_company_overview tool is properly registered"""
tools = await server.list_tools()
overview_tool = next((t for t in tools if t.name == "get_company_overview"), None)
assert overview_tool is not None
assert overview_tool.description is not None
assert "company_code" in overview_tool.inputSchema.get("properties", {})
@pytest.mark.asyncio
async def test_get_company_overview_with_valid_code(self, server):
"""Test get_company_overview with valid company code"""
# Samsung Electronics code
company_code = "005930"
result = await server.call_tool("get_company_overview", {
"company_code": company_code
})
assert result is not None
assert "company_name" in result
assert "stock_code" in result
assert result["stock_code"] == company_code
@pytest.mark.asyncio
async def test_get_company_overview_with_invalid_code(self, server):
"""Test get_company_overview with invalid company code"""
invalid_code = "999999"
with pytest.raises(CompanyNotFoundError):
await server.call_tool("get_company_overview", {
"company_code": invalid_code
})
@pytest.mark.asyncio
async def test_get_financial_statements_tool_exists(self, server):
"""Test that get_financial_statements tool is properly registered"""
tools = await server.list_tools()
financial_tool = next((t for t in tools if t.name == "get_financial_statements"), None)
assert financial_tool is not None
assert financial_tool.description is not None
assert "company_code" in financial_tool.inputSchema.get("properties", {})
@pytest.mark.asyncio
async def test_get_financial_statements_with_valid_code(self, server):
"""Test get_financial_statements with valid company code"""
company_code = "005930"
result = await server.call_tool("get_financial_statements", {
"company_code": company_code,
"period": "1Y"
})
assert result is not None
assert "financial_data" in result
assert len(result["financial_data"]) > 0
@pytest.mark.asyncio
async def test_error_handling_for_tool_calls(self, server):
"""Test error handling for tool calls"""
with pytest.raises(MCPStockDetailsError):
await server.call_tool("nonexistent_tool", {})
@pytest.mark.asyncio
async def test_server_graceful_shutdown(self, server):
"""Test that server shuts down gracefully"""
# This should not raise any exceptions
await server.shutdown()
class TestServerConfiguration:
"""Test server configuration"""
def test_settings_loading(self):
"""Test that settings are loaded correctly"""
settings = get_settings()
assert settings.server_name == "mcp-stock-details"
assert settings.server_version == "1.0.0"
def test_tools_configuration(self):
"""Test tools configuration"""
from src.config import get_tools_config
tools_config = get_tools_config()
assert "get_company_overview" in tools_config
assert "get_financial_statements" in tools_config
# Check parameter specifications
overview_params = tools_config["get_company_overview"]["parameters"]
assert "company_code" in overview_params
assert overview_params["company_code"]["type"] == "string"
# Additional test cases for edge cases and error conditions
class TestErrorHandling:
"""Test error handling scenarios"""
@pytest.fixture
def server(self):
"""Create server instance for error testing"""
return MCPStockDetailsServer()
@pytest.mark.asyncio
async def test_empty_company_code(self, server):
"""Test handling of empty company code"""
with pytest.raises(MCPStockDetailsError):
await server.call_tool("get_company_overview", {
"company_code": ""
})
@pytest.mark.asyncio
async def test_none_company_code(self, server):
"""Test handling of None company code"""
with pytest.raises(MCPStockDetailsError):
await server.call_tool("get_company_overview", {
"company_code": None
})
@pytest.mark.asyncio
async def test_malformed_parameters(self, server):
"""Test handling of malformed parameters"""
with pytest.raises(MCPStockDetailsError):
await server.call_tool("get_company_overview", {
"invalid_param": "value"
})
if __name__ == "__main__":
# Run tests with pytest
pytest.main([__file__, "-v"])