Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I simulate a ParameterNotFound boto3 exception in my unit test?

I want to test some error handling logic, so I want to simulate a the specific exception type in my unit test. I am mocking the call to boto3, but I want to make that mock to raise a ParameterNotFound exception. The code I am testing follows this pattern:

boto3_client = boto3.client('ssm')
try:
    temp_var = boto3_client.get_parameter(Name="Something not found")['Parameter']['Value']
except boto3_client.exceptions.ParameterNotFound:
    ... [logic I want to test]

I have created a unittest mock, but I don't know how to make it raise the exception as this ParameterNotFound exception. I tried the following, but it doesn't work because it gets "exceptions must derive from the base class" when evaluating the except clause:

@patch('patching_config.boto3.client')
def test_sample(self, mock_boto3_client):
        mock_boto3_client.return_value = mock_boto3_client

        def get_parameter_side_effect(**kwargs):
            raise boto3.client.exceptions.ParameterNotFound()

        mock_boto3_client.get_parameter.side_effect = get_parameter_side_effect

How can I simulate a ParameterNotFound boto3 exception in my unit test?

like image 942
Shawn Avatar asked Jan 18 '26 12:01

Shawn


1 Answers

I think the problem was my misunderstanding of how boto3 is raising exceptions. I found an explanation here: https://github.com/boto/boto3/issues/1262 under "Structure of a ClientError"

Structure of a ClientError

Within ClientError (but not BotoCoreError), there will be an operation_name attribute (should be a str) and a response attribute (should be a dict). The response attribute should have the following form (example from a malformed ec2.DescribeImages call):

and also here: https://codeday.me/en/qa/20190306/12210.html

{
    "Error": {
        "Code": "InvalidParameterValue",
        "Message": "The filter 'asdfasdf' is invalid"
    },
    "ResponseMetadata": {
        "RequestId": "aaaabbbb-cccc-dddd-eeee-ffff00001111",
        "HTTPStatusCode": 400,
        "HTTPHeaders": {
            "transfer-encoding": "chunked",
            "date": "Fri, 01 Jan 2100 00:00:00 GMT",
            "connection": "close",
            "server": "AmazonEC2"
        },
        "RetryAttempts": 0
    }
}

It sounds like the exception is thrown as a ClientError which has a ParameterNotFound error code, so I need to change things to

from botocore.exceptions import ClientError

and then

except ClientError as e:

and in the mocking I need to raise a ClientError instead which has the ParameterNotFound as the Code:

raise botocore.exceptions.ClientError({"Error": {"Code": "ParameterNotFound",
                                                 "Message": "Parameter was not found"}}, 
                                      'get_parameter')
like image 142
Shawn Avatar answered Jan 21 '26 02:01

Shawn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!