I'm trying to run some unit tests using moto
and unittest
based off of this example from muhannad0's blog.
Below is my code (minified the table creation as it's not so important).
@mock_dynamodb2
class TestDatabaseFunctions(unittest.TestCase):
def setUp(self):
"""
Create database resource and mock table
"""
print("Setting up")
self.dynamodb = boto3.resource('dynamodb', region_name='eu-west-2')
self.table = self.dynamodb.create_table(TableName='test-table', KeySchema=[{'AttributeName': 'pk', 'KeyType': 'HASH'}, {'AttributeName': 'sk','KeyType': 'RANGE'}], AttributeDefinitions=[{'AttributeName': 'pk', 'AttributeType': 'S'},{'AttributeName': 'sk', 'AttributeType': 'S'}], ProvisionedThroughput={'ReadCapacityUnits': 1, 'WriteCapacityUnits': 1})
print("Waiting until the table exists")
# Wait until the table exists.
self.table.meta.client.get_waiter('table_exists').wait(TableName='test-table')
assert self.table.table_status == 'ACTIVE'
print("Ready to go")
def tearDown(self):
"""
Delete database resource and mock table
"""
print("Tearing down")
self.table.delete()
self.dynamodb = None
print("Teardown complete")
def test_table_exists(self):
"""
Test if our mock table is ready
"""
print("Testing")
self.assertIn('test-table', self.table.name)
print("Test complete")
if __name__ == '__main__':
unittest.main()
When I run it I end up with an error deep in Python 3.8's mock.py
file.
=================================== FAILURES ===================================
___________________ TestDatabaseFunctions.test_table_exists ____________________
../../../env/lib/python3.8/site-packages/moto/core/models.py:102: in wrapper
self.stop()
../../../env/lib/python3.8/site-packages/moto/core/models.py:86: in stop
self.default_session_mock.stop()
../../../env/lib/python3.8/site-packages/mock/mock.py:1563: in stop
return self.__exit__(None, None, None)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <mock.mock._patch object at 0x1128d2a30>, exc_info = (None, None, None)
def __exit__(self, *exc_info):
"""Undo the patch."""
> if self.is_local and self.temp_original is not DEFAULT:
E AttributeError: '_patch' object has no attribute 'is_local'
../../../env/lib/python3.8/site-packages/mock/mock.py:1529: AttributeError
Thanks to my caveman debugging I can say that this error happens after the Teardown complete
message, suggesting that this is happening after the test executes successfully and is only happening after my teardown block finishes up.
I quite like this example by muhannad0 as it uses the class decorator and lets us mock dynamodb in there easily so hopefully we can keep it.
Let me know if you need any more information, you should be able to run this yourself by copying and pasting the code into your preferred IDE and hitting go.
This looks like it's due to an incompatibility between the moto and mock libraries. The issue is being discussed here: https://github.com/spulec/moto/issues/3535
A temporary workaround is to fix those libraries to versions that are compatible. I'm currently fixing mock to 4.0.2 to avoid the AttributeError:
pip install mock==4.0.2