Search code examples
pythonmockingpython-unittestmagicmock

Unittest.mock - how to mock a call to cursor.execute() from connection object?


I am trying to stub out cursor.execute() in the following code with mock such that I can test execute is called with a correctly formatted query:

// Module ABC

def buildAndExecuteQuery( tablesAndColumnsToSelect ):
   '''Build and execute a query.

   Args: tablesAndColumnsToSelect (dict)
         - keys are table names, values are columns

   '''
   query = ..... < logic to build query > ....

   from django.db import connections
   cursor = connections[ 'mydb' ].cursor()
   cursor.execute( query )

How can I accomplish this type of mock in python2.7 with the mock library?


Solution

  • Since I don't know what your query logic is, I modified the query to just accept a sentinel value directly through the tables_and_columns_to_select argument.

    # b_and_ex_q.py
    
    
    def build_and_execute_query(tables_and_columns_to_select):
        """Build and execute a query.
    
        Args: tablesAndColumnsToSelect (dict)
              - keys are table names, values are columns
    
        """
    
        query = tables_and_columns_to_select  # ..... < logic to build query > ....
    
        from django.db import connections
    
        cursor = connections['mydb'].cursor()
        cursor.execute(query)
    

    import unittest
    
    from mock import patch, sentinel
    
    from b_and_ex_q import build_and_execute_query
    
    
    class TestCursorExecute(unittest.TestCase):
        @patch('django.db.connections')
        def test_build_and_execute_query(self, mock_connections):
            # Arrange
            mock_cursor = mock_connections.__getitem__('mydb').cursor.return_value
    
            # Act
            build_and_execute_query(sentinel.t_and_c)
    
            # Assert
            mock_cursor.execute.assert_called_once_with(sentinel.t_and_c)
    
    
    if __name__ == '__main__':
        unittest.main()