You have a series of related calls, each of which returns a new object. If you psycopg2.connect() only psycopg2.connect() , you can follow this chain of calls (each of which .return_value dummy objects) through the .return_value attributes that reference the returned .return_value for such calls:
@mock.patch("psycopg2.connect") def test_super_awesome_stuff(self, mock_connect): expected = [['fake', 'row', 1], ['fake', 'row', 2]] mock_con = mock_connect.return_value
Since you hold references to the dummy connect function, as well as dummy connections and cursor objects, you can also claim that they were called correctly:
mock_connect.assert_called_with(**connection_stuff) mock_con.cursor.called_with(cursor_factory=DictCursor) mock_cur.execute.called_with("Super duper SQL query")
If you do not need to test them, you can simply return_value links to go directly to the result of calling cursor() on the connection object:
@mock.patch("psycopg2.connect") def test_super_awesome_stuff(self, mock_connect): expected = [['fake', 'row', 1], ['fake', 'row' 2]] mock_connect.return_value.cursor.return_value.fetchall.return_value = expected result = super_cool_method() self.assertEqual(result, expected)
Note that if you use the connection as a context manager to automatically commit the transaction and use as to bind the object returned by __enter__() to the new name (for example, with psycopg2.connect(...) as conn: #... ) then you will need to add an extra __enter__.return_value to the call chain:
mock_con_cm = mock_connect.return_value
The same applies to the result with conn.cursor() as cursor: conn.cursor.return_value.__enter__.return_value The conn.cursor.return_value.__enter__.return_value is assigned as target object.