Skip to main content
Glama

Mnemosyne MCP

by MumuTW
test_atlassian_client.py9.94 kB
""" AtlassianClient 契約測試 測試 AtlassianClient 與 MCP Atlassian 服務的 API 契約, 使用模擬伺服器確保測試的獨立性和穩定性。 """ import pytest from aioresponses import aioresponses from mnemosyne.clients.atlassian import AtlassianClient from mnemosyne.core.config import MCPAtlassianSettings from tests.mocks.mcp_atlassian_mock import MCPAtlassianMockServer class TestAtlassianClientContract: """測試 AtlassianClient 與 MCP Atlassian 的 API 契約""" @pytest.fixture def settings(self): """創建測試用配置""" return MCPAtlassianSettings( service_url="http://mcp-atlassian:8001", read_only_mode=True, enabled_tools=[ "confluence_search", "jira_search", "jira_get_issue", ], jira_url="https://company.atlassian.net", jira_username="test@company.com", jira_api_token="test-token", confluence_url="https://company.atlassian.net/wiki", confluence_username="test@company.com", confluence_api_token="test-token", ) @pytest.fixture def mock_server(self): """創建模擬伺服器""" return MCPAtlassianMockServer() @pytest.mark.asyncio async def test_client_initialization(self, settings): """測試客戶端初始化""" client = AtlassianClient(settings) assert client.settings == settings assert client._base_url == "http://mcp-atlassian:8001" assert client.is_configured is True assert client.request_count == 0 assert client.error_count == 0 @pytest.mark.asyncio async def test_health_check_success(self, settings, mock_server): """測試成功的健康檢查""" with aioresponses() as m: mock_server.setup_successful_responses(m) async with AtlassianClient(settings) as client: result = await client.health_check() assert result["status"] == "healthy" assert "response_time_ms" in result assert "data" in result @pytest.mark.asyncio async def test_health_check_failure(self, settings, mock_server): """測試失敗的健康檢查""" with aioresponses() as m: mock_server.setup_error_responses(m) async with AtlassianClient(settings) as client: result = await client.health_check() assert result["status"] == "unhealthy" assert "error" in result assert "response_time_ms" in result @pytest.mark.asyncio async def test_search_jira_issues_success(self, settings, mock_server): """測試成功的 Jira Issue 搜尋""" with aioresponses() as m: mock_server.setup_successful_responses(m) async with AtlassianClient(settings) as client: issues = await client.search_jira_issues("bug fix") assert len(issues) == 2 assert issues[0].key == "DEMO-123" assert issues[0].summary == "修復登入功能錯誤" assert issues[1].key == "DEMO-124" assert issues[1].summary == "新增用戶註冊 API" # 驗證統計信息 stats = client.get_stats() assert stats["request_count"] == 1 assert stats["error_count"] == 0 assert stats["success_rate"] == 100.0 @pytest.mark.asyncio async def test_search_jira_issues_with_project_filter(self, settings, mock_server): """測試帶專案過濾器的 Jira Issue 搜尋""" with aioresponses() as m: # 設置自定義響應,驗證過濾器參數 mock_server.setup_custom_response( m, "POST", "http://mcp-atlassian:8001/jira/search", 200, mock_server.mock_data.create_jira_search_response(), ) async with AtlassianClient(settings) as client: issues = await client.search_jira_issues("bug", project_filter="DEMO") assert len(issues) == 2 @pytest.mark.asyncio async def test_search_jira_issues_tool_disabled(self, settings): """測試工具被禁用時的行為""" # 修改設定,禁用 jira_search settings.enabled_tools = ["confluence_search"] async with AtlassianClient(settings) as client: issues = await client.search_jira_issues("bug fix") assert len(issues) == 0 @pytest.mark.asyncio async def test_get_jira_issue_success(self, settings, mock_server): """測試成功獲取 Jira Issue""" with aioresponses() as m: mock_server.setup_successful_responses(m) async with AtlassianClient(settings) as client: issue = await client.get_jira_issue("DEMO-123") assert issue is not None assert issue.key == "DEMO-123" assert issue.summary == "示例 Jira Issue" assert issue.status == "In Progress" assert issue.priority == "Medium" @pytest.mark.asyncio async def test_get_jira_issue_not_found(self, settings, mock_server): """測試獲取不存在的 Jira Issue""" with aioresponses() as m: mock_server.setup_error_responses(m) async with AtlassianClient(settings) as client: issue = await client.get_jira_issue("NOTFOUND-999") assert issue is None @pytest.mark.asyncio async def test_search_confluence_pages_success(self, settings, mock_server): """測試成功的 Confluence 頁面搜尋""" with aioresponses() as m: mock_server.setup_successful_responses(m) async with AtlassianClient(settings) as client: pages = await client.search_confluence_pages("API") assert len(pages) == 2 assert pages[0].title == "API 開發指南" assert pages[0].space == "DEV" assert pages[1].title == "系統架構設計" assert pages[1].space == "ARCH" @pytest.mark.asyncio async def test_search_confluence_pages_with_space_filter( self, settings, mock_server ): """測試帶空間過濾器的 Confluence 頁面搜尋""" with aioresponses() as m: mock_server.setup_custom_response( m, "POST", "http://mcp-atlassian:8001/confluence/search", 200, mock_server.mock_data.create_confluence_search_response(), ) async with AtlassianClient(settings) as client: pages = await client.search_confluence_pages("API", space_filter="DEV") assert len(pages) == 2 @pytest.mark.asyncio async def test_search_confluence_pages_tool_disabled(self, settings): """測試工具被禁用時的行為""" # 修改設定,禁用 confluence_search settings.enabled_tools = ["jira_search"] async with AtlassianClient(settings) as client: pages = await client.search_confluence_pages("API") assert len(pages) == 0 @pytest.mark.asyncio async def test_error_handling_and_statistics(self, settings, mock_server): """測試錯誤處理和統計信息""" with aioresponses() as m: # 設置錯誤響應 mock_server.setup_error_responses(m) async with AtlassianClient(settings) as client: # 執行多次失敗的請求 await client.search_jira_issues("test") await client.search_confluence_pages("test") await client.health_check() # 檢查統計信息 stats = client.get_stats() assert stats["request_count"] == 3 assert stats["error_count"] == 3 assert stats["success_rate"] == 0.0 assert stats["average_response_time_ms"] > 0 @pytest.mark.asyncio async def test_session_not_initialized_error(self, settings): """測試會話未初始化的錯誤""" client = AtlassianClient(settings) with pytest.raises(RuntimeError, match="Client session not initialized"): await client._make_request("GET", "/health") @pytest.mark.asyncio async def test_data_validation_error_handling(self, settings): """測試數據驗證錯誤處理""" with aioresponses() as m: # 返回無效的 Jira Issue 數據 invalid_data = { "issues": [ { "id": "123", # 缺少必需的 'key' 字段 "summary": "Test", "status": "Open", } ] } m.post( "http://mcp-atlassian:8001/jira/search", status=200, payload=invalid_data, ) async with AtlassianClient(settings) as client: issues = await client.search_jira_issues("test") # 應該優雅地處理驗證錯誤,返回空列表 assert len(issues) == 0 @pytest.mark.asyncio async def test_configuration_check(self): """測試配置檢查""" # 未配置的設定 unconfigured_settings = MCPAtlassianSettings() client = AtlassianClient(unconfigured_settings) assert client.is_configured is False # 已配置的設定 configured_settings = MCPAtlassianSettings( jira_url="https://company.atlassian.net", jira_username="test@company.com", jira_api_token="test-token", ) client = AtlassianClient(configured_settings) assert client.is_configured is True

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/MumuTW/Mnemosyne-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server