I’m unable to make a test that handles when the key value name does not exist:
if not self.key_vault_name:
raise ValueError("Key Vault name is not set in the environment variables.")
this is the class implementation:
from azure.identity import ClientSecretCredential
from azure.keyvault.secrets import SecretClient
from dotenv import load_dotenv
import os
class SecretHandler:
"""
Handles the retrieval of secrets from an Azure Key Vault.
This class uses Azure's ClientSecretCredential for authentication and
SecretClient for accessing the secrets stored in the Azure Key Vault.
The credentials and Key Vault name are loaded from environment variables.
"""
def __init__(self, dotenv_file: str = "srcconfig.env") -> None:
"""
Initializes the SecretHandler instance by loading environment variables
and setting up the credential for Azure Key Vault access using client ID,
tenant ID, and client secret.
"""
load_dotenv(dotenv_path=dotenv_file)
self.key_vault_name = os.getenv("KEY_VAULT_NAME")
if not self.key_vault_name:
raise ValueError("Key Vault name is not set in the environment variables.")
try:
self.credential = ClientSecretCredential(
client_id=os.getenv("AZURE_CLIENT_ID"),
tenant_id=os.getenv("AZURE_TENANT_ID"),
client_secret=os.getenv("AZURE_CLIENT_SECRET"),
)
except Exception as e:
raise ValueError(f"Failed to obtain credential: {e}")
self.secrets = {}
def retrieve_secrets(self) -> None:
"""
Retrieves all secrets from the Azure Key Vault.
This method uses the SecretClient to list all the secret properties
in the Key Vault and then retrieves the actual secret values, storing
them in the `self.secrets` dictionary.
"""
secret_client = SecretClient(
vault_url=f"https://{self.key_vault_name}.vault.azure.net/",
credential=self.credential,
)
try:
secret_properties = secret_client.list_properties_of_secrets()
for secret_property in secret_properties:
secret = secret_client.get_secret(secret_property.name)
self.secrets[secret.name] = secret.value
except Exception as e:
raise ValueError(f"Failed to retrieve secrets: {e}")
Here is my test:
@patch("src.config.secret_handler.ClientSecretCredential", autospec=True)
def test_init_secret_handler_wrong_key_vault(mock_client_secret_credential):
# Mock setup for successful credential initialization
client_secret_credential_instance = Mock()
mock_client_secret_credential.return_value = client_secret_credential_instance
# Mock environment without KEY_VAULT_NAME
with patch.dict('os.environ', {'AZURE_CLIENT_ID': 'test_client_id',
'AZURE_TENANT_ID': 'test_tenant_id',
'AZURE_CLIENT_SECRET': 'test_client_secret'}):
# Test initialization expecting ValueError from SecretHandler
with pytest.raises(ValueError, match="Key Vault name is not set in the environment variables."):
SecretHandler(dotenv_file="test/config/failed_env.env")
When running pytest, I got the following:
FAILED test/config/test_secret_handler.py::test_init_secret_handler_wrong_key_vault – Failed: DID NOT RAISE <class ‘ValueError’>
Any suggestions?
patch.dict
(documentation) adds extra values to a dictionary. It does not remove existing ones unless you pass clear=True
.