mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-04-30 12:40:10 +00:00
feat: add backend unit tests with pytest (207 cases)
This commit is contained in:
parent
9c96495165
commit
cdfea63c5f
12 changed files with 5815 additions and 787 deletions
196
backend/tests/unit/controller/test_tool_controller.py
Normal file
196
backend/tests/unit/controller/test_tool_controller.py
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from app.controller.tool_controller import install_tool
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestToolController:
|
||||
"""Test cases for tool controller endpoints."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_notion_tool_success(self):
|
||||
tool_name = "notion"
|
||||
mock_toolkit = AsyncMock()
|
||||
mock_tools = [MagicMock(), MagicMock()]
|
||||
for tool, name in zip(mock_tools, ["create_page", "update_page"]):
|
||||
tool.func.__name__ = name
|
||||
mock_toolkit.get_tools = MagicMock(return_value=mock_tools)
|
||||
with patch("app.controller.tool_controller.NotionMCPToolkit", return_value=mock_toolkit):
|
||||
result = await install_tool(tool_name)
|
||||
assert result == ["create_page", "update_page"]
|
||||
mock_toolkit.connect.assert_called_once()
|
||||
mock_toolkit.disconnect.assert_called_once()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_unknown_tool(self):
|
||||
result = await install_tool("unknown_tool")
|
||||
assert result == {"error": "Tool not found"}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_notion_tool_connection_failure(self):
|
||||
mock_toolkit = AsyncMock()
|
||||
mock_toolkit.connect.side_effect = Exception("Connection failed")
|
||||
with patch("app.controller.tool_controller.NotionMCPToolkit", return_value=mock_toolkit):
|
||||
with pytest.raises(Exception, match="Connection failed"):
|
||||
await install_tool("notion")
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_notion_tool_get_tools_failure(self):
|
||||
mock_toolkit = AsyncMock()
|
||||
mock_toolkit.get_tools = MagicMock(side_effect=Exception("Failed to get tools"))
|
||||
with patch("app.controller.tool_controller.NotionMCPToolkit", return_value=mock_toolkit):
|
||||
with pytest.raises(Exception, match="Failed to get tools"):
|
||||
await install_tool("notion")
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_notion_tool_disconnect_failure(self):
|
||||
mock_toolkit = AsyncMock()
|
||||
mock_tools = [MagicMock()]
|
||||
mock_tools[0].func.__name__ = "test_tool"
|
||||
mock_toolkit.get_tools = MagicMock(return_value=mock_tools)
|
||||
mock_toolkit.disconnect.side_effect = Exception("Disconnect failed")
|
||||
with patch("app.controller.tool_controller.NotionMCPToolkit", return_value=mock_toolkit):
|
||||
with pytest.raises(Exception, match="Disconnect failed"):
|
||||
await install_tool("notion")
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_notion_tool_empty_tools(self):
|
||||
mock_toolkit = AsyncMock()
|
||||
mock_toolkit.get_tools = MagicMock(return_value=[])
|
||||
with patch("app.controller.tool_controller.NotionMCPToolkit", return_value=mock_toolkit):
|
||||
result = await install_tool("notion")
|
||||
assert result == []
|
||||
mock_toolkit.connect.assert_called_once()
|
||||
mock_toolkit.disconnect.assert_called_once()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_notion_tool_with_complex_tools(self):
|
||||
mock_toolkit = AsyncMock()
|
||||
names = ["create_database", "query_database", "update_block", "delete_page"]
|
||||
mock_tools = []
|
||||
for name in names:
|
||||
mt = MagicMock()
|
||||
mt.func.__name__ = name
|
||||
mock_tools.append(mt)
|
||||
mock_toolkit.get_tools = MagicMock(return_value=mock_tools)
|
||||
with patch("app.controller.tool_controller.NotionMCPToolkit", return_value=mock_toolkit):
|
||||
result = await install_tool("notion")
|
||||
assert result == names
|
||||
mock_toolkit.connect.assert_called_once()
|
||||
mock_toolkit.disconnect.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
class TestToolControllerIntegration:
|
||||
"""Integration tests for tool controller."""
|
||||
|
||||
def test_install_notion_tool_endpoint_integration(self, client: TestClient):
|
||||
"""Test install Notion tool endpoint through FastAPI test client."""
|
||||
tool_name = "notion"
|
||||
|
||||
mock_toolkit = AsyncMock()
|
||||
mock_tools = [MagicMock(), MagicMock()]
|
||||
mock_tools[0].func.__name__ = "create_page"
|
||||
mock_tools[1].func.__name__ = "update_page"
|
||||
mock_toolkit.get_tools = MagicMock(return_value=mock_tools)
|
||||
|
||||
with patch("app.controller.tool_controller.NotionMCPToolkit", return_value=mock_toolkit):
|
||||
response = client.post(f"/install/tool/{tool_name}")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == ["create_page", "update_page"]
|
||||
|
||||
def test_install_unknown_tool_endpoint_integration(self, client: TestClient):
|
||||
"""Test install unknown tool endpoint through FastAPI test client."""
|
||||
tool_name = "unknown_tool"
|
||||
|
||||
response = client.post(f"/install/tool/{tool_name}")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"error": "Tool not found"}
|
||||
|
||||
def test_install_notion_tool_endpoint_with_connection_error(self, client: TestClient):
|
||||
"""Test install Notion tool endpoint when connection fails."""
|
||||
tool_name = "notion"
|
||||
|
||||
mock_toolkit = AsyncMock()
|
||||
mock_toolkit.connect.side_effect = Exception("Connection failed")
|
||||
|
||||
with patch("app.controller.tool_controller.NotionMCPToolkit", return_value=mock_toolkit):
|
||||
# The exception should be raised by the endpoint since there's no error handling
|
||||
with pytest.raises(Exception, match="Connection failed"):
|
||||
response = client.post(f"/install/tool/{tool_name}")
|
||||
|
||||
|
||||
@pytest.mark.model_backend
|
||||
class TestToolControllerWithRealMCP:
|
||||
"""Tests that require real MCP connections (marked for selective running)."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_notion_tool_with_real_connection(self):
|
||||
"""Test Notion tool installation with real MCP connection."""
|
||||
tool_name = "notion"
|
||||
|
||||
# This test would connect to real Notion MCP server
|
||||
# Requires actual MCP server setup and credentials
|
||||
# Marked as model_backend test for selective execution
|
||||
assert True # Placeholder
|
||||
|
||||
@pytest.mark.very_slow
|
||||
async def test_install_and_test_all_notion_tools(self):
|
||||
"""Test installation and functionality of all Notion tools (very slow test)."""
|
||||
# This test would install and test each Notion tool individually
|
||||
# Marked as very_slow for execution only in full test mode
|
||||
assert True # Placeholder
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestToolControllerErrorCases:
|
||||
"""Test error and edge cases for tool installation."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_tool_with_malformed_tool_response(self):
|
||||
mock_toolkit = AsyncMock()
|
||||
tools = [MagicMock(), object()] # Second item lacks func
|
||||
tools[0].func.__name__ = "valid_tool"
|
||||
mock_toolkit.get_tools = MagicMock(return_value=tools)
|
||||
with patch("app.controller.tool_controller.NotionMCPToolkit", return_value=mock_toolkit):
|
||||
with pytest.raises(AttributeError):
|
||||
await install_tool("notion")
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_tool_with_none_toolkit(self):
|
||||
with patch("app.controller.tool_controller.NotionMCPToolkit", return_value=None):
|
||||
with pytest.raises(AttributeError):
|
||||
await install_tool("notion")
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_tool_with_special_characters_in_name(self):
|
||||
result = await install_tool("notion@#$%")
|
||||
assert result == {"error": "Tool not found"}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_tool_with_empty_string_name(self):
|
||||
result = await install_tool("")
|
||||
assert result == {"error": "Tool not found"}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_tool_with_none_name(self):
|
||||
result = await install_tool(None)
|
||||
assert result == {"error": "Tool not found"}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_notion_tool_partial_failure(self):
|
||||
mock_toolkit = AsyncMock()
|
||||
mock_toolkit.connect.return_value = None
|
||||
tools = [MagicMock(), MagicMock(), MagicMock()]
|
||||
tools[0].func.__name__ = "create_page"
|
||||
tools[1].func.__name__ = "update_page"
|
||||
tools[2].func = None
|
||||
mock_toolkit.get_tools = MagicMock(return_value=tools)
|
||||
mock_toolkit.disconnect.return_value = None
|
||||
with patch("app.controller.tool_controller.NotionMCPToolkit", return_value=mock_toolkit):
|
||||
with pytest.raises(AttributeError):
|
||||
await install_tool("notion")
|
||||
Loading…
Add table
Add a link
Reference in a new issue