Skip to main content
Glama
test_client.py5.3 kB
import pytest import asyncio from unittest.mock import patch, MagicMock, AsyncMock # Since we are using an editable install, we can use absolute imports from ollama_mcp.client import OllamaClient, ModelInfo @pytest.fixture def client(): """Provides a fresh OllamaClient for each test.""" return OllamaClient() @pytest.mark.asyncio @patch('ollama.AsyncClient') async def test_health_check_healthy(mock_async_client, client): """Test a successful health check when the Ollama server is responsive.""" # Arrange mock_instance = mock_async_client.return_value mock_instance.ps = AsyncMock() # Create a mock model object that mimics the ollama library response mock_model = MagicMock() mock_model.model_dump.return_value = { 'model': 'test-model', 'size': 1000, 'digest': 'abc123', 'modified_at': '2024-01-01T00:00:00Z' } mock_list_response = MagicMock() mock_list_response.models = [mock_model] mock_instance.list = AsyncMock(return_value=mock_list_response) # Act health = await client.health_check() # Assert assert health["healthy"] is True assert health["models_count"] == 1 assert "Ollama server responsive" in health["message"] mock_instance.ps.assert_awaited_once() @pytest.mark.asyncio @patch('ollama.AsyncClient') async def test_health_check_unhealthy_timeout(mock_async_client, client): """Test an unsuccessful health check due to a timeout.""" # Arrange mock_instance = mock_async_client.return_value mock_instance.ps.side_effect = asyncio.TimeoutError # Act health = await client.health_check() # Assert assert health["healthy"] is False assert "Ollama server timeout" in health["error"] @pytest.mark.asyncio @patch('ollama.AsyncClient') async def test_list_models_success(mock_async_client, client): """Test successfully listing models.""" # Arrange mock_instance = mock_async_client.return_value # Create mock model objects that mimic the ollama library response mock_model1 = MagicMock() mock_model1.model_dump.return_value = { 'model': 'llama3', 'size': 12345, 'digest': 'abc123', 'modified_at': '2023-01-01T00:00:00Z' } mock_model2 = MagicMock() mock_model2.model_dump.return_value = { 'model': 'qwen', 'size': 67890, 'digest': 'def456', 'modified_at': '2023-01-02T00:00:00Z' } mock_list_response = MagicMock() mock_list_response.models = [mock_model1, mock_model2] mock_instance.list = AsyncMock(return_value=mock_list_response) # Act result = await client.list_models() # Assert assert result["success"] is True assert result["count"] == 2 # Client now returns dicts, not ModelInfo objects assert isinstance(result["models"][0], dict) assert result["models"][0]["name"] == 'llama3' assert result["models"][0]["size_human"] == '12.1 KB' @pytest.mark.asyncio @patch('ollama.AsyncClient') async def test_list_models_api_error(mock_async_client, client): """Test handling of an API error when listing models.""" # Arrange mock_instance = mock_async_client.return_value mock_instance.list.side_effect = Exception("API connection failed") # Act result = await client.list_models() # Assert assert result["success"] is False assert "API connection failed" in result["error"] assert result["models"] == [] @pytest.mark.asyncio @patch('ollama.AsyncClient') async def test_chat_success(mock_async_client, client): """Test a successful chat session.""" # Arrange mock_instance = mock_async_client.return_value mock_chat_response = { 'message': {'content': 'This is a test response.'}, 'eval_count': 10, 'total_duration': 12345 } mock_instance.chat = AsyncMock(return_value=mock_chat_response) # Act result = await client.chat("test-model", "Hello") # Assert assert result["success"] is True assert result["response"] == 'This is a test response.' assert result["model"] == "test-model" mock_instance.chat.assert_awaited_once() @pytest.mark.asyncio @patch('ollama.AsyncClient') async def test_remove_model_not_found(mock_async_client, client): """Test attempting to remove a model that does not exist.""" # Arrange import ollama mock_instance = mock_async_client.return_value mock_instance.delete.side_effect = ollama.ResponseError("Model not found", status_code=404) # Act result = await client.remove_model("nonexistent-model") # Assert assert result["success"] is False assert "not found" in result["error"] def test_model_info_size_human_readable(): """Test the human-readable size conversion in ModelInfo.""" # Test cases for various sizes - ModelInfo requires 4 args: name, size, digest, modified_at assert ModelInfo("test", 100, "", "2024-01-01").size_human == "100.0 B" assert ModelInfo("test", 2 * 1024, "", "2024-01-01").size_human == "2.0 KB" assert ModelInfo("test", 3 * 1024**2, "", "2024-01-01").size_human == "3.0 MB" assert ModelInfo("test", 4 * 1024**3, "", "2024-01-01").size_human == "4.0 GB" assert ModelInfo("test", 5 * 1024**4, "", "2024-01-01").size_human == "5.0 TB"

Latest Blog Posts

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/paolodalprato/ollama-mcp-server'

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