Search code examples
amazon-dynamodbpytestboto3python-unittest.mock

How to patch Boto3.resource DynamoDb Table within a pytest test method


I'm trying to use this answer as an example to test that a dynamo table is not written to.

Because I am using moto to test my reads & writes, I have to do the import inside the test case. I cannot get patch to take, keep getting SSL errors I've tried:

@patch('boto3.resource')
def my_test(self, mock_boto_resource)
    import code_under_test

    table_mock = MagicMock()
    ddb_mock = MagicMock().return_value(table_mock)
    mock_boto_resource.return_value = ddb_mock

    code_under_test.execute

    table_mock.assert_called_once()

I've tried moving the import after assigning the resource. I've tried using context def my_test(self)

    table_mock = MagicMock()
    ddb_mock = MagicMock().return_value(table_mock)
    with patch('boto3.resource') as mock_boto_resource
        mock_boto_resource.return_value = ddb_mock
        import code_under_test

        code_under_test.execute

    table_mock.assert_called_once()

Again tried moving the import around. A normal execute() does a query & put. I want to test in some cases that the query does not occur, but I cannot get that far, because I keep getting botocor.exception.SSLError

I also found this answer, but having trouble figuring out what the equivalent method in resource is.


Solution

  • This ended up being fairly simple once I figured out what I was trying to patch where. I'm not patching boto3, just the Table item.

    Code under test my_module/my_file.py

    import boto3
    
    ddb = boto3.resource('dynamodb')
    table = ddb.Table(os.environ.get('DDB_TABLE_NAME'))
    
    def handler(event, context):
    

    test to patch table

    def test_prior_not_called_with_no_lock(self):
        #Code under Test
        import my_module.my_file as my_file
        
        event = {<event data for test>}
    
        with patch('my_module.my_file.table') as mock_table:
            my_file.handler(event, None)
        
        #Assert
            mock_table.put_item.assert_called_once()
            mock_table.query.assert_not_called()