|
7 | 7 |
|
8 | 8 | """
|
9 | 9 |
|
10 |
| -from unittest.mock import patch |
| 10 | +from unittest.mock import patch, MagicMock |
11 | 11 |
|
12 | 12 | from mcpgateway.config import Settings, get_settings
|
13 | 13 |
|
14 | 14 |
|
15 | 15 | def test_settings_default_values():
|
16 |
| - """Test that Settings has expected default values.""" |
17 |
| - settings = Settings() |
18 |
| - assert settings.app_name == "MCP Gateway" |
19 |
| - assert settings.host == "0.0.0.0" |
| 16 | + """ |
| 17 | + Verify the class defaults only, independent of anything in the |
| 18 | + developer's local .env file. Passing ``_env_file=None`` tells |
| 19 | + Pydantic not to load any environment file. |
| 20 | + """ |
| 21 | + settings = Settings(_env_file=None) |
| 22 | + |
| 23 | + assert settings.app_name == "MCP_Gateway" |
| 24 | + assert settings.host == "127.0.0.1" |
20 | 25 | assert settings.port == 4444
|
21 | 26 | assert settings.database_url == "sqlite:///./mcp.db"
|
22 | 27 | assert settings.basic_auth_user == "admin"
|
23 | 28 | assert settings.basic_auth_password == "changeme"
|
24 | 29 | assert settings.auth_required is True
|
25 | 30 |
|
26 | 31 |
|
| 32 | + |
27 | 33 | def test_api_key_property():
|
28 | 34 | """Test the api_key property."""
|
29 | 35 | settings = Settings(basic_auth_user="test_user", basic_auth_password="test_pass")
|
@@ -53,17 +59,35 @@ def test_supports_transport_properties():
|
53 | 59 |
|
54 | 60 | @patch("mcpgateway.config.Settings")
|
55 | 61 | def test_get_settings_caching(mock_settings):
|
56 |
| - """Test that get_settings caches the result.""" |
57 |
| - mock_settings.return_value = "test_settings" |
| 62 | + """ |
| 63 | + Ensure get_settings() calls the Settings constructor exactly once and |
| 64 | + then serves the cached object on every additional call. |
| 65 | + """ |
| 66 | + # Clear the cache created at import-time. |
| 67 | + get_settings.cache_clear() |
| 68 | + |
| 69 | + # Two distinct mock Settings instances, each with the methods that |
| 70 | + # get_settings() invokes (validate_transport / validate_database). |
| 71 | + settings_instance_1 = MagicMock() |
| 72 | + settings_instance_2 = MagicMock() |
| 73 | + |
| 74 | + # Each mock must expose these methods so AttributeError is not raised. |
| 75 | + settings_instance_1.validate_transport.return_value = None |
| 76 | + settings_instance_1.validate_database.return_value = None |
| 77 | + settings_instance_2.validate_transport.return_value = None |
| 78 | + settings_instance_2.validate_database.return_value = None |
| 79 | + |
| 80 | + # First call should return instance_1; any further constructor calls |
| 81 | + # would return instance_2 (but they shouldn't happen). |
| 82 | + mock_settings.side_effect = [settings_instance_1, settings_instance_2] |
58 | 83 |
|
59 |
| - # First call should create settings |
60 | 84 | result1 = get_settings()
|
61 |
| - assert result1 == "test_settings" |
| 85 | + assert result1 is settings_instance_1 |
62 | 86 |
|
63 |
| - # Second call should use cached value |
64 |
| - mock_settings.return_value = "new_settings" |
| 87 | + # Even after we change what the constructor would return, the cached |
| 88 | + # object must still be served. |
65 | 89 | result2 = get_settings()
|
66 |
| - assert result2 == "test_settings" # Should still be the first value |
| 90 | + assert result2 is settings_instance_1 |
67 | 91 |
|
68 |
| - # Settings should only be created once |
| 92 | + # The constructor should have been invoked exactly once. |
69 | 93 | assert mock_settings.call_count == 1
|
0 commit comments