Justin S
Justin S

Reputation: 1459

aws boto3 client Stubber help stubbing unit tests

I'm trying to write some unit tests for aws RDS. Currently, the start stop rds api calls have not yet been implemented in moto. I tried just mocking out boto3 but ran into all sorts of weird issues. I did some googling and found http://botocore.readthedocs.io/en/latest/reference/stubber.html

So I have tried to implement the example for rds but the code appears to be behaving like the normal client, even though I have stubbed it. Not sure what's going on or if I am stubbing correctly?

from LambdaRdsStartStop.lambda_function import lambda_handler
from LambdaRdsStartStop.lambda_function import AWS_REGION

def tests_turn_db_on_when_cw_event_matches_tag_value(self, mock_boto):
    client = boto3.client('rds', AWS_REGION)
    stubber = Stubber(client)
    response = {u'DBInstances': [some copy pasted real data here], extra_info_about_call: extra_info}
    stubber.add_response('describe_db_instances', response, {})

    with stubber:
        r = client.describe_db_instances()
        lambda_handler({u'AutoStart': u'10:00:00+10:00/mon'}, 'context')

so the mocking WORKS for the first line inside the stubber and the value of r is returned as my stubbed data. When I try and go into my lambda_handler method inside my lambda_function.py and still use the stubbed client it behaves like a normal unstubbed client:

lambda_function.py

def lambda_handler(event, context):
    rds_client = boto3.client('rds', region_name=AWS_REGION)
    rds_instances = rds_client.describe_db_instances()

error output:

  File "D:\dev\projects\virtual_envs\rds_sloth\lib\site-packages\botocore\auth.py", line 340, in add_auth
    raise NoCredentialsError
NoCredentialsError: Unable to locate credentials

Upvotes: 5

Views: 13904

Answers (1)

rocky4570
rocky4570

Reputation: 76

You will need to patch boto3 where it is called in the routine that you will be testing. Also Stubber responses appear to be consumed on each call and thus will require another add_response for each stubbed call as below:

def tests_turn_db_on_when_cw_event_matches_tag_value(self, mock_boto):
    client = boto3.client('rds', AWS_REGION)
    stubber = Stubber(client)
    # response data below should match aws documentation otherwise more errors due to botocore error handling
    response = {u'DBInstances': [{'DBInstanceIdentifier': 'rds_response1'}, {'DBInstanceIdentifierrd': 'rds_response2'}]}

    stubber.add_response('describe_db_instances', response, {})
    stubber.add_response('describe_db_instances', response, {})

    with mock.patch('lambda_handler.boto3') as mock_boto3:
        with stubber:
            r = client.describe_db_instances() # first_add_response consumed here
            mock_boto3.client.return_value = client
            response=lambda_handler({u'AutoStart': u'10:00:00+10:00/mon'}, 'context')  # second_add_response would be consumed here
            # asert.equal(r,response)

Upvotes: 4

Related Questions