0

I have a module which makes object of dynamoDB client. The module is external and does not belong to my code. I am trying to unit test enclosingClass


class enclosingClass:
    def enclosing_function():
       ddb_client = get_ddb_client(role)
       ddb_client.query()
       
# Module in my code which returns dynamoDB client object

from x.y.common import get_aws_client

def get_ddb_client(role):
    return get_aws_client('dynamodb', assume_role_arn=role)

In my code I am getting the aws client object and calling query on it. I want to mock both the things

  1. return value of get_aws_client should be a mocked object
  2. Call to query dynamoDB should happen on mocked object.

But when I run unit test, I am getting the actual dynamoDB object and calling query on the dynamoDB object returns 'expected bytes or bytearray, but got 'MagicMock'

I am not understanding what to do in this. very new to python and not sure how do I return a mocked dynamoDb client object

@mock.patch("x.y.common.get_aws_client")
@mock.patch("boto3.client")
def test_hello_world_task(get_aws_client_mock, mock_client):
    
    get_aws_client_mock.return_value= mock_client
    mock_client.query.return_value = None

    enclosing_class.enclosing_function() # the method call to enclosing function

A007
  • 107
  • 1
  • 12
  • I've had good experience using moto for testing modules using boto: https://github.com/spulec/moto – Tzane Sep 07 '21 at 07:33

1 Answers1

0

Your issue: dynamoDB client is being initiated within enclosing_function.

Solution: Create the object (object being mocked) outside of function under test and pass it as a parameter [also known as dependency injection].

class enclosingClass:
    def enclosing_function(get_ddb_client):
       ddb_client = get_ddb_client # could avoid this line by directly taking the parameter as ddb_client
       ddb_client.query()


@mock.patch("x.y.common.get_aws_client")
@mock.patch("boto3.client")
def test_hello_world_task(get_aws_client_mock, mock_client):
    
    get_aws_client_mock.return_value= mock_client
    mock_client.query.return_value = None

    enclosing_class.enclosing_function(get_aws_client_mock) # the method call to enclosing function

Hope this answers. Thanks.

lulu
  • 191
  • 1
  • 7