Home > front end >  Mocking AWS session.Session() got AttributeError: 'function' object has no attribute '
Mocking AWS session.Session() got AttributeError: 'function' object has no attribute '

Time:01-26

I need to write unit tests for the following class function, which returns the EC2 instances of AWS, to be tested.

class C:
    def f(cls, session, filters):
            # ....
            instances = session.resource('ec2').instances.filter(Filters=filters)
            # ....
            return instances

I want to test if session.resource('ec2').instances.filter() is called with parameter Filters=filters.

import boto3
import boto3.session
import pytest
from moto import mock_ec2

@mock_ec2
def test_get_nodes():
    '''Test get node'''
    session = boto3.session.Session(region_name='')
    filters = None
    C.f(session, filters)
    assert session.resource('ec2').instances.filter.call_count == 1

However, the test got the following error?

>           raise ValueError("Invalid endpoint: %s" % endpoint_url)
E           ValueError: Invalid endpoint: https://ec2..amazonaws.com

I don't want the test function connect to the AWS console actually. Anyway, it got the following error after I set the region_name with a proper value:

>       assert session.resource('ec2').instances.filter.call_count == 1
E       AttributeError: 'function' object has no attribute 'call_count'

CodePudding user response:

The region is not set here :

session = boto3.session.Session(region_name='')

Try with the region filled in.

CodePudding user response:

It looks like you're trying to use traditional mocking approaches (like testing the number of calls, catching the arguments, etc) in combination with Moto. But Moto does not expose any of that information.

Moto is more like an in-memory AWS instance. That means you can use any (supported) boto3 request, and Moto will intercept that request and behave like AWS does - but without actually making the request (and incurring any costs).

A traditional Moto test case (in pseudo-case) would look like this:

assert len(session.resource('ec2').instances) == 0
ec2_client.run_instances(..)
assert len(session.resource('ec2').instances) == 2
assert len(session.resource('ec2').instances.filter) == 1

None of that checks whether methods are called - it uses boto3-requests to verify that previous boto3-requests were successful, like you're writing an integration test against AWS itself.

Edit:
If you are concerned about making requests to AWS itself, it's worth setting dummy environment variables that reset your access key/secret key during testing.
See http://docs.getmoto.org/en/latest/docs/getting_started.html#recommended-usage

It is also possible to use a nonexistent-region, for even more peace of mind.

os.environ["MOTO_ALLOW_NONEXISTENT_REGION"] = True
os.environ["AWS_DEFAULT_REGION"] = "antarctica"

See the FAQ here: http://docs.getmoto.org/en/latest/docs/faq.html#can-i-mock-the-default-aws-region

  •  Tags:  
  • Related