Search code examples
pythonpytestboto3pytest-mock

How to mock the boto3 client session requests for secretsmanager to either return a specific response or raise an exception


Given code like:

def do_stuff():

    session = boto3.session.Session()
    client = session.client(service_name="secretsmanager", region_name=region_name)
    client.get_secret_value(SecretId=sendgrid_api_key_arn)

how do I mock client.get_secret_value("some-value") to return some value

and how do I mock it to throw an exception

@patch("boto3.session")
def test_get_sendgrid_api_key_secret_when_client_error(mock_session):
        session = mock_session.Session();
        client = session.client()
        client.get_secret_value().return_value = 
                 {"SecretString": "my-secret"} <- this is wrapped in a MagicMock which is useless.

Solution

  • You need to set a tree of return values:

    • boto3.session.Session needs to return a mock object
    • That mock object needs a client method that returns another mock object
    • And that mock object needs a get_secret_value method that returns a fake value

    If I assume that target.py exists and contains:

    import boto3.session
    
    
    def do_stuff():
        session = boto3.session.Session()
        client = session.client(service_name="secretsmanager", region_name='myregion')
        return client.get_secret_value(SecretId='some-secret-id')
    

    Then I can test it like this:

    from unittest import mock
    
    import target
    
    
    @mock.patch("boto3.session.Session")
    def test_do_stuff(mock_session_class):
        mock_session_object = mock.Mock()
        mock_client = mock.Mock()
        mock_client.get_secret_value.return_value = {'SecretString': 'my-secret'}
        mock_session_object.client.return_value = mock_client
        mock_session_class.return_value = mock_session_object
    
        res = target.do_stuff()
        assert res['SecretString'] == 'my-secret'
    

    This works, although I suspect there's a more graceful way to set it up.