MnemoCore / tests /test_di_migration.py
Granis87's picture
Upload folder using huggingface_hub
c3a3710 verified
"""
Tests for Dependency Injection Migration
=========================================
Verifies that the singleton pattern has been properly removed
and replaced with dependency injection.
"""
import pytest
from unittest.mock import MagicMock, AsyncMock, patch
class TestAsyncRedisStorageDI:
"""Tests for AsyncRedisStorage dependency injection."""
def test_no_get_instance_method(self):
"""AsyncRedisStorage should not have get_instance class method."""
from mnemocore.core.async_storage import AsyncRedisStorage
assert not hasattr(AsyncRedisStorage, 'get_instance'), \
"AsyncRedisStorage should not have get_instance method"
def test_constructor_accepts_parameters(self):
"""AsyncRedisStorage constructor should accept explicit parameters."""
from mnemocore.core.async_storage import AsyncRedisStorage
# Create with explicit parameters to verify they work
storage = AsyncRedisStorage(
url="redis://test:6379/0",
stream_key="test:stream",
max_connections=5,
socket_timeout=10,
password="testpass",
)
# Verify attributes are set
assert storage.stream_key == "test:stream"
def test_constructor_with_mock_client(self):
"""AsyncRedisStorage should accept a mock client for testing."""
from mnemocore.core.async_storage import AsyncRedisStorage
mock_client = MagicMock()
storage = AsyncRedisStorage(client=mock_client)
assert storage.redis_client is mock_client
class TestQdrantStoreDI:
"""Tests for QdrantStore dependency injection."""
def test_no_get_instance_method(self):
"""QdrantStore should not have get_instance class method."""
from mnemocore.core.qdrant_store import QdrantStore
assert not hasattr(QdrantStore, 'get_instance'), \
"QdrantStore should not have get_instance method"
def test_constructor_accepts_parameters(self):
"""QdrantStore constructor should accept explicit parameters."""
from mnemocore.core.qdrant_store import QdrantStore
store = QdrantStore(
url="http://test:6333",
api_key="test-key",
dimensionality=8192,
collection_hot="test_hot",
collection_warm="test_warm",
)
assert store.url == "http://test:6333"
assert store.api_key == "test-key"
assert store.dim == 8192
assert store.collection_hot == "test_hot"
assert store.collection_warm == "test_warm"
class TestContainer:
"""Tests for the dependency injection container."""
def test_container_exists(self):
"""Container module should exist and be importable."""
from mnemocore.core.container import Container, build_container
assert Container is not None
assert build_container is not None
def test_build_container_creates_dependencies(self):
"""build_container should create all required dependencies."""
from mnemocore.core.container import build_container
from mnemocore.core.config import HAIMConfig
# Create a minimal config
config = HAIMConfig()
with patch('mnemocore.core.container.AsyncRedisStorage') as mock_redis_class, \
patch('mnemocore.core.container.QdrantStore') as mock_qdrant_class:
mock_redis_class.return_value = MagicMock()
mock_qdrant_class.return_value = MagicMock()
container = build_container(config)
assert container.config is config
assert container.redis_storage is not None
assert container.qdrant_store is not None
def test_container_dataclass_fields(self):
"""Container should have expected fields."""
from mnemocore.core.container import Container
from mnemocore.core.config import HAIMConfig
config = HAIMConfig()
container = Container(config=config)
assert hasattr(container, 'config')
assert hasattr(container, 'redis_storage')
assert hasattr(container, 'qdrant_store')
class TestTierManagerDI:
"""Tests for TierManager dependency injection."""
def test_constructor_accepts_config(self):
"""TierManager constructor should accept config parameter."""
from mnemocore.core.tier_manager import TierManager
from mnemocore.core.config import HAIMConfig
config = HAIMConfig()
with patch('mnemocore.core.tier_manager.HNSW_AVAILABLE', False), \
patch('mnemocore.core.tier_manager.FAISS_AVAILABLE', False):
manager = TierManager(config=config)
assert manager.config is config
def test_constructor_accepts_qdrant_store(self):
"""TierManager constructor should accept qdrant_store parameter."""
from mnemocore.core.tier_manager import TierManager
from mnemocore.core.config import HAIMConfig
config = HAIMConfig()
mock_qdrant = MagicMock()
with patch('mnemocore.core.tier_manager.HNSW_AVAILABLE', False), \
patch('mnemocore.core.tier_manager.FAISS_AVAILABLE', False):
manager = TierManager(config=config, qdrant_store=mock_qdrant)
assert manager.qdrant is mock_qdrant
assert manager.use_qdrant is True
class TestHAIMEngineDI:
"""Tests for HAIMEngine dependency injection."""
def test_constructor_accepts_config(self):
"""HAIMEngine constructor should accept config parameter."""
from mnemocore.core.engine import HAIMEngine
from mnemocore.core.config import HAIMConfig
config = HAIMConfig()
# Patch at tier_manager level since that's where HNSW/FAISS is used
with patch('mnemocore.core.tier_manager.HNSW_AVAILABLE', False), \
patch('mnemocore.core.tier_manager.FAISS_AVAILABLE', False):
engine = HAIMEngine(config=config)
assert engine.config is config
def test_constructor_accepts_tier_manager(self):
"""HAIMEngine constructor should accept tier_manager parameter."""
from mnemocore.core.engine import HAIMEngine
from mnemocore.core.config import HAIMConfig
from mnemocore.core.tier_manager import TierManager
config = HAIMConfig()
with patch('mnemocore.core.tier_manager.HNSW_AVAILABLE', False), \
patch('mnemocore.core.tier_manager.FAISS_AVAILABLE', False):
tier_manager = TierManager(config=config)
engine = HAIMEngine(config=config, tier_manager=tier_manager)
assert engine.tier_manager is tier_manager
class TestConsolidationWorkerDI:
"""Tests for ConsolidationWorker dependency injection."""
def test_constructor_accepts_storage(self):
"""ConsolidationWorker constructor should accept storage parameter."""
from mnemocore.core.consolidation_worker import ConsolidationWorker
mock_storage = MagicMock()
mock_tier_manager = MagicMock()
worker = ConsolidationWorker(
storage=mock_storage,
tier_manager=mock_tier_manager,
)
assert worker.storage is mock_storage
assert worker.tier_manager is mock_tier_manager
class TestNoSingletonPattern:
"""Tests to ensure singleton pattern is fully removed."""
def test_no_singleton_instances(self):
"""Classes should not have _instance class attribute for singletons."""
from mnemocore.core.async_storage import AsyncRedisStorage
from mnemocore.core.qdrant_store import QdrantStore
# _instance is the typical singleton storage attribute
assert not hasattr(AsyncRedisStorage, '_instance') or \
AsyncRedisStorage._instance is None or \
'_instance' not in AsyncRedisStorage.__dict__
# Note: QdrantStore might have _instance from object base,
# but shouldn't have it defined explicitly for singleton use
if hasattr(QdrantStore, '_instance'):
# Check it's not being used as singleton storage
assert '_instance' not in QdrantStore.__dict__ or \
QdrantStore.__dict__['_instance'] is None
def test_multiple_instances_independent(self):
"""Creating multiple instances should work independently."""
from mnemocore.core.async_storage import AsyncRedisStorage
mock_client1 = MagicMock()
mock_client2 = MagicMock()
storage1 = AsyncRedisStorage(client=mock_client1)
storage2 = AsyncRedisStorage(client=mock_client2)
# Each should have its own client
assert storage1.redis_client is mock_client1
assert storage2.redis_client is mock_client2
assert storage1 is not storage2