0

To test the following functino, I want to assert .filter() is called once with parameter filters.

def get_instances(session: boto3.session.Session, filters):
    instances = session.resource('ec2').instances.filter(Filters=filters)
    return instances

I tried to write the unit test,

def test_get_instance():
    mocked_session: boto3.session.Session = boto3.session.Session()

    def resource(service_name) -> boto3.resources.base.ServiceResource:
        if service_name == 'ec2':
            return MagicMock()
        raise Exception('Parameter should be ec2')

    mocked_session.resource = MagicMock(side_effect=resource)  # resource is set?
    mocked_session.resource('ec2').instances = MagicMock()
    # mocked_session.resource('ec2').instances. ??? # not finished

    filters = None
    Node.get_nodes(mocked_session, filters)
    assert session.resource('ec2').instances.filter.call_count == 1

However, the test function got the following error

>       assert session.resource('ec2').instances.filter.call_count == 1
E       AttributeError: 'function' object has no attribute 'resource'
ca9163d9
  • 27,283
  • 64
  • 210
  • 413
  • should it not be `assert mocked_session.resource('ec2')...` instead of `assert session.resource('ec2')...` (like simple 'typo') ? However I suggested another way to do that in my answer, using the built-in `monckeypatch` fixture from `pytest` let me know if it helped – jossefaz Jan 25 '22 at 09:31

1 Answers1

0

You can use the built-in monckeypatch fixture for that purpose.

def test_get_instance(monkeypatch):
    # ... your code
    filter_calls = []
    monkeypatch.setattr(mocked_session.resource('ec2'), 'filter', lambda Filters: filter_calls.append(1))
    assert len(filter_calls) == 1

I did not test it with the boto3 lib, however, the idea is here.

jossefaz
  • 3,312
  • 4
  • 17
  • 40
  • @ca9163d9 : Please let me know if it worked for you and what did you change to make it work (That way I could update my answer) – jossefaz Jan 25 '22 at 09:29