"""Unit tests for configuration management system.""" from unittest.mock import MagicMock, Mock, patch import pytest from arbitrade.config.service import ConfigurationService from arbitrade.config.settings import Settings from arbitrade.storage.repositories import AuditRepository @pytest.fixture def mock_settings(): """Create a mock settings object.""" settings = Mock(spec=Settings) settings.app_env = "test" return settings @pytest.fixture def mock_store(): """Create a mock database store with context manager.""" store = Mock() cursor = Mock() cursor.fetchone.return_value = None cursor.fetchall.return_value = [] cursor.execute.return_value = cursor cntx = MagicMock() cntx.__enter__.return_value = cursor store.connect.return_value = cntx return store @pytest.fixture def mock_audit_repo(): """Create a mock audit repository.""" audit_repo = Mock(spec=AuditRepository) return audit_repo def test_configuration_service_initialization(mock_settings, mock_store, mock_audit_repo): """Test that ConfigurationService initializes correctly.""" # Create service instance service = ConfigurationService(mock_settings, mock_store, mock_audit_repo) # Verify attributes are set assert service._settings == mock_settings assert service._store == mock_store assert service._audit_repo == mock_audit_repo assert service._config_version == 0 assert isinstance(service._loaded_settings, dict) def test_configuration_service_get_setting(mock_settings, mock_store, mock_audit_repo): """Test getting configuration settings.""" # Create service instance service = ConfigurationService(mock_settings, mock_store, mock_audit_repo) # Set up mock loaded settings service._loaded_settings = {"test_key": "test_value"} # Test getting existing setting result = service.get_setting("test_key", "default") assert result == "test_value" # Test getting non-existing setting with default result = service.get_setting("non_existing", "default") assert result == "default" def test_configuration_service_set_setting(mock_settings, mock_store, mock_audit_repo): """Test setting configuration settings.""" # Create service instance service = ConfigurationService(mock_settings, mock_store, mock_audit_repo) # Mock the repository with patch("arbitrade.storage.repositories.ConfigSettingRepository") as mock_repo_class: mock_repo_instance = Mock() mock_repo_class.return_value = mock_repo_instance # Mock the setting creation mock_created_setting = Mock() mock_created_setting.updated_at = "2023-01-01T00:00:00" mock_repo_instance.create_setting.return_value = mock_created_setting mock_repo_instance.get_setting.return_value = None # force create path # Set a setting service.set_setting("test_key", "test_value", "test_user") # Verify repository was called mock_repo_instance.create_setting.assert_called_once() def test_configuration_service_hot_reload_detection(mock_settings, mock_store, mock_audit_repo): """Test hot-reload detection functionality.""" # Create service instance service = ConfigurationService(mock_settings, mock_store, mock_audit_repo) # Initially should not be outdated assert service.is_config_outdated() is False # Test with mock repository that returns a timestamp with patch("arbitrade.storage.repositories.ConfigSettingRepository") as mock_repo_class: mock_repo_instance = Mock() mock_repo_class.return_value = mock_repo_instance # Mock the latest updated at timestamp from datetime import datetime mock_repo_instance.get_latest_updated_at.return_value = datetime.now() # Should detect as outdated when timestamp exists assert service.is_config_outdated() is True def test_configuration_service_reload_if_changed(mock_settings, mock_store, mock_audit_repo): """Test hot-reload functionality.""" # Create service instance service = ConfigurationService(mock_settings, mock_store, mock_audit_repo) # Mock the repository with patch("arbitrade.storage.repositories.ConfigSettingRepository") as mock_repo_class: mock_repo_instance = Mock() mock_repo_class.return_value = mock_repo_instance # Mock the latest updated at timestamp to return None initially mock_repo_instance.get_latest_updated_at.return_value = None mock_repo_instance.list_settings.return_value = [] # Mock the latest updated at timestamp to return a value from datetime import datetime mock_repo_instance.get_latest_updated_at.return_value = datetime.now() # Should reload when outdated result = service.reload_if_changed() assert result is True assert service.get_config_version() == 1 def test_configuration_service_get_config_version(mock_settings, mock_store, mock_audit_repo): """Test getting configuration version.""" # Create service instance service = ConfigurationService(mock_settings, mock_store, mock_audit_repo) # Should start at version 0 assert service.get_config_version() == 0 # After setting a value, version should increment with patch("arbitrade.storage.repositories.ConfigSettingRepository") as mock_repo_class: mock_repo_instance = Mock() mock_repo_class.return_value = mock_repo_instance mock_created_setting = Mock() mock_created_setting.updated_at = "2023-01-01T00:00:00" mock_repo_instance.create_setting.return_value = mock_created_setting mock_repo_instance.get_setting.return_value = None service.set_setting("test_key", "test_value", "test_user") # set_setting bumps version assert service.get_config_version() == 1 def test_configuration_service_get_last_updated_at(mock_settings, mock_store, mock_audit_repo): """Test getting last updated timestamp.""" # Create service instance service = ConfigurationService(mock_settings, mock_store, mock_audit_repo) # Should start with None assert service.get_last_updated_at() is None # After setting a value, should have timestamp with patch("arbitrade.storage.repositories.ConfigSettingRepository") as mock_repo_class: mock_repo_instance = Mock() mock_repo_class.return_value = mock_repo_instance mock_created_setting = Mock() mock_created_setting.updated_at = "2023-01-01T00:00:00" mock_repo_instance.create_setting.return_value = mock_created_setting mock_repo_instance.get_setting.return_value = None service.set_setting("test_key", "test_value", "test_user") # set_setting updates _last_updated_at from mock assert service.get_last_updated_at() is not None