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?
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')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With