Skip to content

Commit

Permalink
tests: adding coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
Rafael Marques committed Jul 14, 2024
1 parent 6a7fb2c commit 9a4d4ec
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 16 deletions.
6 changes: 3 additions & 3 deletions pydantic_settings_aws/aws.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ def _get_secrets_content(secret: dict[str, Any]) -> Optional[str]:
if secret_binary:
try:
secrets_content = secret_binary.decode("utf-8")
except ValueError as val_err:
logger.error(f"Error decoding secrets content: {val_err}")
except (AttributeError, ValueError) as err:
logger.error(f"Error decoding secrets content: {err}")

raise val_err
raise err

return secrets_content
3 changes: 3 additions & 0 deletions tests/aws_mocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
TARGET_SECRET_CONTENT = "pydantic_settings_aws.aws._get_secrets_content"


def mock_secrets_content_invalid_json(*args):
return ClientMock(secret_string="invalid-json")

def mock_secrets_content_empty(*args):
return ClientMock(secret_string=None)

Expand Down
57 changes: 57 additions & 0 deletions tests/aws_test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import json
from unittest import mock

import pytest

from pydantic import ValidationError
from pydantic_settings_aws import aws

from .aws_mocks import (
Expand All @@ -12,6 +14,7 @@
BaseSettingsMock,
mock_create_client,
mock_secrets_content_empty,
mock_secrets_content_invalid_json,
)
from .boto3_mocks import SessionMock

Expand Down Expand Up @@ -48,3 +51,57 @@ def test_get_secrets_content_must_raise_value_error_if_secrets_content_is_none(

with pytest.raises(ValueError):
aws.get_secrets_content(settings)


@mock.patch(TARGET_BOTO3_CLIENT, mock_secrets_content_invalid_json)
def test_should_not_obfuscate_json_error_in_case_of_invalid_secrets(*args):
settings = BaseSettingsMock()
settings.model_config = {
"secrets_name": "secrets/name",
"aws_region": "region",
"aws_profile": "profile",
}

with pytest.raises(json.decoder.JSONDecodeError):
aws.get_secrets_content(settings)


def test_get_secrets_content_must_get_binary_content_if_string_is_not_set(*args):
content = {
"SecretBinary": json.dumps({"username": "admin"}).encode("utf-8")
}
secret_content = aws._get_secrets_content(content)

assert isinstance(secret_content, str)


def test_get_secrets_content_must_not_hide_decode_error_if_not_binary_in_secret_binary(*args):
content = {
"SecretBinary": json.dumps({"username": "admin"})
}

with pytest.raises(AttributeError):
aws._get_secrets_content(content)


def test_get_secrets_content_must_return_none_if_neither_string_nor_binary_are_present(*args):
secret_content = aws._get_secrets_content({})

assert secret_content is None


def test_get_secrets_content_must_return_none_if_binary_is_present_but_none(*args):
content = {
"SecretBinary": None
}
secret_content = aws._get_secrets_content(content)

assert secret_content is None


def test_get_secrets_args_must_not_shadow_pydantic_validation_if_required_args_are_not_present(*args):
settings = BaseSettingsMock()
settings.model_config = {}

with pytest.raises(ValidationError):
aws._get_secrets_args(settings)
24 changes: 12 additions & 12 deletions tests/boto3_mocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,33 @@


class SessionMock:

def __init__(self, *args, **kwargs) -> None:
pass

def client(self, name: str):
return self



class ClientMock:

def __init__(self, secret_string: str = None, raise_client_err: bool = False) -> None:
def __init__(
self,
secret_string: str = None,
secret_bytes: bytes = None
) -> None:
self.secret_string = secret_string
self.raise_client_err = raise_client_err

def get_secret_value(self, SecretId=None, VersionId=None, VersionStage=None):
if self.raise_client_err:
raise
self.secret_bytes = secret_bytes

def get_secret_value(
self, SecretId=None, VersionId=None, VersionStage=None
):
return {
"ARN": "string",
"Name": "string",
"VersionId": "string",
"SecretBinary": b"bytes",
"SecretString": str(self.secret_string),
"SecretBinary": self.secret_bytes,
"SecretString": self.secret_string,
"VersionStages": [
"string",
],
"CreatedDate": datetime.datetime.utcnow()
"CreatedDate": datetime.datetime.utcnow(),
}
4 changes: 3 additions & 1 deletion tests/settings_mocks.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
from typing import Optional

from pydantic import BaseModel
from pydantic_settings import SettingsConfigDict
Expand All @@ -8,7 +9,7 @@
from .boto3_mocks import ClientMock

secrets_with_username_and_password = json.dumps(
{"username": "myusername", "password": "password1234"}
{"username": "myusername", "password": "password1234", "name": None}
)

mock_secrets_with_username_and_pwd = ClientMock(
Expand All @@ -24,6 +25,7 @@ class MySecretsWithClientConfig(SecretsManagerBaseSettings):

username: str
password: str
name: Optional[str] = None


secrets_with_nested_content = json.dumps(
Expand Down
File renamed without changes.

0 comments on commit 9a4d4ec

Please sign in to comment.