mock secret manager using pytest

4.5k views Asked by At

I am trying to mock secret manager. Here is the code which is written for secret manager using boto3 which I am trying to mock and test.

utils.py

import boto3

secret_id = os.environ.get("SECRETS") 
client = boto3.client('secretsmanager')
response = client.get_secret_value(SecretId=secret_id)
secrets = json.loads(response['SecretString'])
S3_BUCKET_NAME = secrets["S3_BUCKET_NAME"]
SQS_QUEUE_NAME = secrets["SQS_Queue_Name"]

these variables are then used in different methods.

conftest.py

@pytest.fixture(scope='session', autouse=True)
def secret_manager_resource(aws_credentials):
    """Secret Manager mock client"""
    with mock_secretsmanager():
        conn = boto3.client("secretsmanager", region_name="us-east-1")
        logger.info(f"Secret manager connection {conn}")
        yield conn

test_file.py

@contextmanager
def secret_manager_setup(secret_manager_resource):

    secret_manager_resource.create_secret(Name="test", SecretString="""{"S3_BUCKET_NAME": "test","SQS_Queue_Name": "test_queue"}""")
    yield

class TestSecretManager:
    def test_secret_manager(self, secret_manager_resource):
        with secret_manager_setup(secret_manager_resource):
            try:
                result = secret_manager_resource.get_secret_value(SecretId="test")
                json_result = json.loads(result['SecretString'])
                assert json_result["S3_BUCKET_NAME"] == "test"
                assert json_result["SQS_Queue_Name"] == "test_queue"
            except Exception as err:
                print("Error ---", err)

class TestClass:
   def test_some_class(test_var):
     from functions.something.some import something
     something = someClass({}, param)

When I run pytest it directly goes inside TestClass and calls secret Manager and throws error as it is trying to connect to actual secret manager. Could someone suggest me what can be done to over come this issue?

1

There are 1 answers

9
Bert Blommers On

TestClass is not mocked - so I wouldn't expect that to work. You could use Moto as a class-decorator to ensure everything inside someClass is mocked.

Note that the class-decorator creates a mock around test-methods only, so the code-under-test would have to be inside a test-method for this to work.

@mock_secretsmanager()
class TestClass:

    def test_something():
        from functions.something.some import something
        something = someClass({}, param)

See http://docs.getmoto.org/en/latest/docs/getting_started.html#class-decorator for the documentation and more examples around this.