Skip to content

Commit 2ac8eac

Browse files
Fix running tests when google-cloud-secret-manager is not installed (#602)
Co-authored-by: Hasan Ramezani <hasan.r67@gmail.com>
1 parent 871f6be commit 2ac8eac

File tree

1 file changed

+127
-125
lines changed

1 file changed

+127
-125
lines changed

tests/test_source_gcp_secret_manager.py

Lines changed: 127 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@
2323

2424
@pytest.fixture
2525
def mock_secret_client(mocker: MockerFixture):
26-
if not gcp_secret_manager:
27-
pytest.skip('pydantic-settings[gcp-secret-manager] is not installed')
28-
2926
client = mocker.Mock(spec=SecretManagerServiceClient)
3027

3128
# Mock common_project_path
@@ -79,125 +76,130 @@ def mock_google_auth(mocker: MockerFixture):
7976
)
8077

8178

82-
def test_secret_manager_mapping_init(secret_manager_mapping):
83-
assert secret_manager_mapping._project_id == 'test-project'
84-
assert len(secret_manager_mapping._loaded_secrets) == 0
85-
86-
87-
def test_secret_manager_mapping_gcp_project_path(secret_manager_mapping, mock_secret_client):
88-
secret_manager_mapping._gcp_project_path
89-
mock_secret_client.common_project_path.assert_called_once_with('test-project')
90-
91-
92-
def test_secret_manager_mapping_secret_names(secret_manager_mapping):
93-
names = secret_manager_mapping._secret_names
94-
assert names == ['test-secret']
95-
96-
97-
def test_secret_manager_mapping_getitem_success(secret_manager_mapping):
98-
value = secret_manager_mapping['test-secret']
99-
assert value == 'test-value'
100-
101-
102-
def test_secret_manager_mapping_getitem_nonexistent_key(secret_manager_mapping):
103-
with pytest.raises(KeyError):
104-
_ = secret_manager_mapping['nonexistent-secret']
105-
106-
107-
def test_secret_manager_mapping_getitem_access_error(secret_manager_mapping, mocker):
108-
secret_manager_mapping._secret_client.access_secret_version = mocker.Mock(side_effect=Exception('Access denied'))
109-
110-
with pytest.raises(KeyError):
111-
_ = secret_manager_mapping['test-secret']
112-
113-
114-
def test_secret_manager_mapping_iter(secret_manager_mapping):
115-
assert list(secret_manager_mapping) == ['test-secret']
116-
117-
118-
def test_settings_source_init_with_defaults(mock_google_auth, test_settings):
119-
source = GoogleSecretManagerSettingsSource(test_settings)
120-
assert source._project_id == 'default-project'
121-
122-
123-
def test_settings_source_init_with_custom_values(mocker, test_settings):
124-
credentials = mocker.Mock()
125-
source = GoogleSecretManagerSettingsSource(test_settings, credentials=credentials, project_id='custom-project')
126-
assert source._project_id == 'custom-project'
127-
assert source._credentials == credentials
128-
129-
130-
def test_settings_source_init_with_custom_values_no_project_raises_error(mocker, test_settings):
131-
credentials = mocker.Mock()
132-
mocker.patch('pydantic_settings.sources.providers.gcp.google_auth_default', return_value=(mocker.Mock(), None))
133-
134-
with pytest.raises(AttributeError):
135-
_ = GoogleSecretManagerSettingsSource(test_settings, credentials=credentials)
136-
137-
138-
def test_settings_source_load_env_vars(mock_secret_client, mocker, test_settings):
139-
credentials = mocker.Mock()
140-
source = GoogleSecretManagerSettingsSource(test_settings, credentials=credentials, project_id='test-project')
141-
source._secret_client = mock_secret_client
142-
143-
env_vars = source._load_env_vars()
144-
assert isinstance(env_vars, GoogleSecretManagerMapping)
145-
assert env_vars.get('test-secret') == 'test-value'
146-
assert env_vars.get('another_secret') is None
147-
148-
149-
def test_settings_source_repr(test_settings):
150-
source = GoogleSecretManagerSettingsSource(test_settings, project_id='test-project')
151-
assert 'test-project' in repr(source)
152-
assert 'GoogleSecretManagerSettingsSource' in repr(source)
153-
154-
155-
def test_pydantic_base_settings(mock_secret_client, monkeypatch, mocker):
156-
monkeypatch.setenv('ANOTHER_SECRET', 'yep_this_one')
157-
158-
class Settings(BaseSettings, case_sensitive=False):
159-
test_secret: str = Field(..., alias='test-secret')
160-
another_secret: str = Field(..., alias='ANOTHER_SECRET')
161-
162-
@classmethod
163-
def settings_customise_sources(
164-
cls,
165-
settings_cls: type[BaseSettings],
166-
init_settings: PydanticBaseSettingsSource,
167-
env_settings: PydanticBaseSettingsSource,
168-
dotenv_settings: PydanticBaseSettingsSource,
169-
file_secret_settings: PydanticBaseSettingsSource,
170-
) -> tuple[PydanticBaseSettingsSource, ...]:
171-
google_secret_manager_settings = GoogleSecretManagerSettingsSource(
172-
settings_cls, secret_client=mock_secret_client
173-
)
174-
return (init_settings, env_settings, dotenv_settings, file_secret_settings, google_secret_manager_settings)
175-
176-
settings = Settings() # type: ignore
177-
assert settings.another_secret == 'yep_this_one'
178-
assert settings.test_secret == 'test-value'
179-
180-
181-
def test_pydantic_base_settings_with_unknown_attribute(mock_secret_client, monkeypatch, mocker):
182-
from pydantic_core._pydantic_core import ValidationError
183-
184-
class Settings(BaseSettings, case_sensitive=False):
185-
test_secret: str = Field(..., alias='test-secret')
186-
another_secret: str = Field(..., alias='ANOTHER_SECRET')
187-
188-
@classmethod
189-
def settings_customise_sources(
190-
cls,
191-
settings_cls: type[BaseSettings],
192-
init_settings: PydanticBaseSettingsSource,
193-
env_settings: PydanticBaseSettingsSource,
194-
dotenv_settings: PydanticBaseSettingsSource,
195-
file_secret_settings: PydanticBaseSettingsSource,
196-
) -> tuple[PydanticBaseSettingsSource, ...]:
197-
google_secret_manager_settings = GoogleSecretManagerSettingsSource(
198-
settings_cls, secret_client=mock_secret_client
199-
)
200-
return (init_settings, env_settings, dotenv_settings, file_secret_settings, google_secret_manager_settings)
201-
202-
with pytest.raises(ValidationError):
203-
_ = Settings()
79+
@pytest.mark.skipif(not gcp_secret_manager, reason='pydantic-settings[gcp-secret-manager] is not installed')
80+
class TestGoogleSecretManagerSettingsSource:
81+
"""Test GoogleSecretManagerSettingsSource."""
82+
83+
def test_secret_manager_mapping_init(self, secret_manager_mapping):
84+
assert secret_manager_mapping._project_id == 'test-project'
85+
assert len(secret_manager_mapping._loaded_secrets) == 0
86+
87+
def test_secret_manager_mapping_gcp_project_path(self, secret_manager_mapping, mock_secret_client):
88+
secret_manager_mapping._gcp_project_path
89+
mock_secret_client.common_project_path.assert_called_once_with('test-project')
90+
91+
def test_secret_manager_mapping_secret_names(self, secret_manager_mapping):
92+
names = secret_manager_mapping._secret_names
93+
assert names == ['test-secret']
94+
95+
def test_secret_manager_mapping_getitem_success(self, secret_manager_mapping):
96+
value = secret_manager_mapping['test-secret']
97+
assert value == 'test-value'
98+
99+
def test_secret_manager_mapping_getitem_nonexistent_key(self, secret_manager_mapping):
100+
with pytest.raises(KeyError):
101+
_ = secret_manager_mapping['nonexistent-secret']
102+
103+
def test_secret_manager_mapping_getitem_access_error(self, secret_manager_mapping, mocker):
104+
secret_manager_mapping._secret_client.access_secret_version = mocker.Mock(
105+
side_effect=Exception('Access denied')
106+
)
107+
108+
with pytest.raises(KeyError):
109+
_ = secret_manager_mapping['test-secret']
110+
111+
def test_secret_manager_mapping_iter(self, secret_manager_mapping):
112+
assert list(secret_manager_mapping) == ['test-secret']
113+
114+
def test_settings_source_init_with_defaults(self, mock_google_auth, test_settings):
115+
source = GoogleSecretManagerSettingsSource(test_settings)
116+
assert source._project_id == 'default-project'
117+
118+
def test_settings_source_init_with_custom_values(self, mocker, test_settings):
119+
credentials = mocker.Mock()
120+
source = GoogleSecretManagerSettingsSource(test_settings, credentials=credentials, project_id='custom-project')
121+
assert source._project_id == 'custom-project'
122+
assert source._credentials == credentials
123+
124+
def test_settings_source_init_with_custom_values_no_project_raises_error(self, mocker, test_settings):
125+
credentials = mocker.Mock()
126+
mocker.patch('pydantic_settings.sources.providers.gcp.google_auth_default', return_value=(mocker.Mock(), None))
127+
128+
with pytest.raises(AttributeError):
129+
_ = GoogleSecretManagerSettingsSource(test_settings, credentials=credentials)
130+
131+
def test_settings_source_load_env_vars(self, mock_secret_client, mocker, test_settings):
132+
credentials = mocker.Mock()
133+
source = GoogleSecretManagerSettingsSource(test_settings, credentials=credentials, project_id='test-project')
134+
source._secret_client = mock_secret_client
135+
136+
env_vars = source._load_env_vars()
137+
assert isinstance(env_vars, GoogleSecretManagerMapping)
138+
assert env_vars.get('test-secret') == 'test-value'
139+
assert env_vars.get('another_secret') is None
140+
141+
def test_settings_source_repr(self, test_settings):
142+
source = GoogleSecretManagerSettingsSource(test_settings, project_id='test-project')
143+
assert 'test-project' in repr(source)
144+
assert 'GoogleSecretManagerSettingsSource' in repr(source)
145+
146+
def test_pydantic_base_settings(self, mock_secret_client, monkeypatch, mocker):
147+
monkeypatch.setenv('ANOTHER_SECRET', 'yep_this_one')
148+
149+
class Settings(BaseSettings, case_sensitive=False):
150+
test_secret: str = Field(..., alias='test-secret')
151+
another_secret: str = Field(..., alias='ANOTHER_SECRET')
152+
153+
@classmethod
154+
def settings_customise_sources(
155+
cls,
156+
settings_cls: type[BaseSettings],
157+
init_settings: PydanticBaseSettingsSource,
158+
env_settings: PydanticBaseSettingsSource,
159+
dotenv_settings: PydanticBaseSettingsSource,
160+
file_secret_settings: PydanticBaseSettingsSource,
161+
) -> tuple[PydanticBaseSettingsSource, ...]:
162+
google_secret_manager_settings = GoogleSecretManagerSettingsSource(
163+
settings_cls, secret_client=mock_secret_client
164+
)
165+
return (
166+
init_settings,
167+
env_settings,
168+
dotenv_settings,
169+
file_secret_settings,
170+
google_secret_manager_settings,
171+
)
172+
173+
settings = Settings() # type: ignore
174+
assert settings.another_secret == 'yep_this_one'
175+
assert settings.test_secret == 'test-value'
176+
177+
def test_pydantic_base_settings_with_unknown_attribute(self, mock_secret_client, monkeypatch, mocker):
178+
from pydantic_core._pydantic_core import ValidationError
179+
180+
class Settings(BaseSettings, case_sensitive=False):
181+
test_secret: str = Field(..., alias='test-secret')
182+
another_secret: str = Field(..., alias='ANOTHER_SECRET')
183+
184+
@classmethod
185+
def settings_customise_sources(
186+
cls,
187+
settings_cls: type[BaseSettings],
188+
init_settings: PydanticBaseSettingsSource,
189+
env_settings: PydanticBaseSettingsSource,
190+
dotenv_settings: PydanticBaseSettingsSource,
191+
file_secret_settings: PydanticBaseSettingsSource,
192+
) -> tuple[PydanticBaseSettingsSource, ...]:
193+
google_secret_manager_settings = GoogleSecretManagerSettingsSource(
194+
settings_cls, secret_client=mock_secret_client
195+
)
196+
return (
197+
init_settings,
198+
env_settings,
199+
dotenv_settings,
200+
file_secret_settings,
201+
google_secret_manager_settings,
202+
)
203+
204+
with pytest.raises(ValidationError):
205+
_ = Settings()

0 commit comments

Comments
 (0)