4

So I have a class S3 in file/s3.py with the following init:

class S3:
    def __init__(self):
        self.s3_client = boto3.client("s3")

    def get_object(self):
        s3_object = self.s3_client.get_object()
        return s3_object

As you can see, the boto3.client class has a method named get_object() as well. I'm testing my custom get_object() method from another file but don't want to actaully make a boto3.client call to AWS services.

test.py

class TestS3Class(unittest.TestCase):
    """TestCase for file/s3.py"""

    def setUp(self):
        """Creates an instance of the live S3 class for testing"""
        self.s3_test_client = S3()

    @patch('boto3.client')
    def test_get_object(self, mock_client):
        """"""
        mock_client.get_object.return_value = {'key': 'value'}
        self.assertIsInstance(self.s3_test_client.get_object(), dict)

At the moment I'm getting AssertionError: None is not an instance of <class 'dict'> as a response, so I'm not sure if I'm patching something or not, but it's definitely not setting boto3.client.get_object()'s return value to the dictionary object.

Any hints on how to mock that self.s3_client = boto3.client()?

1
  • I fear it has something to do with the fact that my class function is named the same as the boto3.client method, get_object(). Don't know what's wrong though Commented Oct 19, 2019 at 21:33

1 Answer 1

1

boto3.client returns an instance of a dynamically-created class based on the first argument (see source), so you cannot use the patch method, which requires that the target object be importable.

Instead, you can monkey-patch the get_object attribute of the class object of the client with a Mock object that returns your desired dict when called:

class TestS3Class(unittest.TestCase):
    def setUp(self):
        self.s3_test_client = S3()
        self.s3_test_client.s3_client.__class__.get_object = Mock(return_value={'key': 'value'})

    def test_get_object(self):
        self.assertIsInstance(self.s3_test_client.get_object(), dict)

Demo: https://repl.it/@blhsing/MarriedDeficientNumerator

Sign up to request clarification or add additional context in comments.

2 Comments

Ah dang, I burned quite a bit of time trying to figure that out. Came across this hint about runtime a little while ago too, but it didn't register. Yep, that seems to have worked. Thanks @blhsing.
Oh, and I guess I should have guessed from the fact that it takes an argument ec2, s3, etc to create the right client class...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.