Skip to main content
Glama

MCP Memory Service

test_fastapi_dependencies.py7.03 kB
""" Unit tests for FastAPI dependency injection. These tests verify that the actual dependency injection chain works correctly, catching issues like import-time default parameter evaluation. Added to prevent production bugs like v8.12.0 where: def get_memory_service(storage: MemoryStorage = get_storage()) was evaluated at import time when _storage was None. """ import pytest import pytest_asyncio import asyncio import tempfile import os from unittest.mock import MagicMock @pytest_asyncio.fixture async def temp_storage(): """Create a temporary storage for testing.""" from mcp_memory_service.storage.sqlite_vec import SqliteVecMemoryStorage from mcp_memory_service.web.dependencies import set_storage with tempfile.TemporaryDirectory() as tmpdir: db_path = os.path.join(tmpdir, "test.db") storage = SqliteVecMemoryStorage(db_path) await storage.initialize() set_storage(storage) yield storage storage.close() @pytest.mark.asyncio async def test_get_storage_dependency_callable(temp_storage): """Test that get_storage() dependency is callable without errors.""" from mcp_memory_service.web.dependencies import get_storage # Should be callable assert callable(get_storage) # Should not raise when called storage = get_storage() assert storage is not None assert storage is temp_storage def test_get_memory_service_dependency_callable(): """Test that get_memory_service() dependency is callable without errors.""" from mcp_memory_service.web.dependencies import get_memory_service # Should be callable assert callable(get_memory_service) # Should not raise when called try: service = get_memory_service() assert service is not None except Exception as e: pytest.fail(f"get_memory_service() raised unexpected exception: {e}") def test_get_storage_uses_depends_not_default_param(): """Test that get_storage is used via Depends(), not as default parameter. This prevents the v8.12.0 bug where: def get_memory_service(storage: MemoryStorage = get_storage()) was evaluated at import time. """ import inspect from mcp_memory_service.web.dependencies import get_memory_service from fastapi.params import Depends # Get function signature sig = inspect.signature(get_memory_service) # Check if storage parameter exists if 'storage' in sig.parameters: storage_param = sig.parameters['storage'] # If it has a default, it should be Depends(...), not a function call if storage_param.default != inspect.Parameter.empty: # Default should be a Depends instance, not the result of get_storage() # Check the type name since Depends is not a simple type assert type(storage_param.default).__name__ == 'Depends', \ "storage parameter should use Depends(get_storage), not get_storage()" @pytest.mark.asyncio async def test_dependency_chain_storage_to_service(temp_storage): """Test that the dependency chain from storage → service works.""" from mcp_memory_service.web.dependencies import get_storage, get_memory_service # Get storage storage = get_storage() assert storage is not None # Get service (should use the storage) service = get_memory_service() assert service is not None # Service should have a storage reference assert hasattr(service, 'storage') @pytest.mark.asyncio async def test_get_storage_returns_singleton(temp_storage): """Test that get_storage() returns the same instance (singleton pattern).""" from mcp_memory_service.web.dependencies import get_storage storage1 = get_storage() storage2 = get_storage() # Should be the same instance assert storage1 is storage2, "get_storage() should return singleton" def test_get_memory_service_returns_new_instance(): """Test that get_memory_service() returns new instances (not singleton).""" from mcp_memory_service.web.dependencies import get_memory_service service1 = get_memory_service() service2 = get_memory_service() # They use the same storage but are different service instances # (This is OK because MemoryService is stateless) assert isinstance(service1, type(service2)) def test_dependencies_module_has_required_functions(): """Test that dependencies module exports required functions.""" from mcp_memory_service.web import dependencies # Core dependency functions assert hasattr(dependencies, 'get_storage') assert hasattr(dependencies, 'get_memory_service') # Should be callable assert callable(dependencies.get_storage) assert callable(dependencies.get_memory_service) @pytest.mark.asyncio async def test_storage_dependency_is_initialized(temp_storage): """Test that storage returned by get_storage() is properly initialized.""" from mcp_memory_service.web.dependencies import get_storage storage = get_storage() # Check it has expected methods (from base class) assert hasattr(storage, 'store') assert hasattr(storage, 'get_all_memories') assert hasattr(storage, 'get_stats') assert hasattr(storage, 'delete') @pytest.mark.asyncio async def test_async_dependencies_work(temp_storage): """Test that async dependencies work correctly. Some storage operations are async, so we need to verify they work. """ from mcp_memory_service.web.dependencies import get_storage storage = get_storage() # get_stats is async and was the source of issue #191 stats = await storage.get_stats() assert isinstance(stats, dict) assert 'total_memories' in stats def test_dependency_injection_doesnt_fail_on_import(): """Test that importing dependencies module doesn't cause errors. This catches import-time evaluation bugs. """ try: # This should not raise import mcp_memory_service.web.dependencies import mcp_memory_service.web.app # App should be created successfully from mcp_memory_service.web.app import app assert app is not None except Exception as e: pytest.fail(f"Import-time error in dependencies: {e}") def test_memory_service_has_required_methods(): """Test that MemoryService has all required methods.""" from mcp_memory_service.web.dependencies import get_memory_service service = get_memory_service() # Core methods from MemoryService class required_methods = [ 'store_memory', 'retrieve_memories', 'delete_memory', 'list_memories', # Not get_all_memories 'search_by_tag', 'get_memory_by_hash', 'health_check', ] for method in required_methods: assert hasattr(service, method), f"MemoryService missing {method}" assert callable(getattr(service, method)) if __name__ == "__main__": # Allow running tests directly for quick verification pytest.main([__file__, "-v"])

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/doobidoo/mcp-memory-service'

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