如何Mock pyodbc cursor.messages以覆盖单元测试分支逻辑
如何Mock pyodbc cursor.messages实现execute_read方法分支全覆盖
我需要测试execute_read方法的if/else分支逻辑,但始终无法正确Mockcursor.messages的条件分支,现有单元测试只覆盖了部分场景,希望实现全分支覆盖。相关代码如下:
def execute_read(self, query): dbconn = pyodbc.connect(self.connection_string, convert_unicode=True) with dbconn.cursor() as cur: cursor = cur.execute(query) if not cursor.messages: res = cursor.fetchall() else: raise Exception(cursor.messages[0][1]) return res # 现有单元测试 @patch.object(pyodbc, 'connect') def test_execute_read(self, pyodbc_mock): pyodbc_mock.return_value = MagicMock() self.assertIsNotNone(execute_read('query'))
解决方案
要覆盖两个分支,需要精准Mock pyodbc的调用链,包括连接对象、游标对象,以及execute返回实例的messages属性和fetchall方法。
测试if分支(无消息,正常返回结果)
让cursor.messages为空列表,触发正常返回逻辑:
from unittest.mock import patch, MagicMock import unittest import pyodbc # 替换成实际包含execute_read的类所在模块 from your_module import YourDBClass class TestExecuteRead(unittest.TestCase): @patch.object(pyodbc, 'connect') def test_execute_read_normal_case(self, mock_connect): # Mock数据库连接 mock_dbconn = MagicMock() mock_connect.return_value = mock_dbconn # Mock游标(处理with语句的__enter__) mock_cur = MagicMock() mock_dbconn.cursor.return_value.__enter__.return_value = mock_cur # Mock execute返回的游标实例,设置messages为空 mock_execute_cursor = MagicMock() mock_execute_cursor.messages = [] mock_execute_cursor.fetchall.return_value = [('id1', 'name1'), ('id2', 'name2')] mock_cur.execute.return_value = mock_execute_cursor # 执行测试 db_instance = YourDBClass() result = db_instance.execute_read('SELECT * FROM users') # 断言 self.assertEqual(result, [('id1', 'name1'), ('id2', 'name2')]) mock_cur.execute.assert_called_once_with('SELECT * FROM users') mock_execute_cursor.fetchall.assert_called_once()
测试else分支(有消息,抛出异常)
让cursor.messages包含错误信息,触发异常抛出逻辑:
@patch.object(pyodbc, 'connect') def test_execute_read_error_case(self, mock_connect): # Mock数据库连接 mock_dbconn = MagicMock() mock_connect.return_value = mock_dbconn # Mock游标 mock_cur = MagicMock() mock_dbconn.cursor.return_value.__enter__.return_value = mock_cur # Mock execute返回的游标实例,设置错误消息 mock_execute_cursor = MagicMock() # 模拟pyodbc的messages格式:(状态码, 错误信息) mock_execute_cursor.messages = [(100, 'Invalid SQL syntax')] mock_cur.execute.return_value = mock_execute_cursor # 执行测试并断言异常 db_instance = YourDBClass() with self.assertRaises(Exception) as exc_context: db_instance.execute_read('INVALID SQL') self.assertEqual(str(exc_context.exception), 'Invalid SQL syntax') mock_cur.execute.assert_called_once_with('INVALID SQL')
关键注意点
with dbconn.cursor() as cur会调用游标对象的__enter__方法,所以必须Mock这个方法的返回值为游标实例。cur.execute(query)返回的是pyodbc游标对象本身,需要单独Mock这个返回实例的messages属性,而不是外层的mock_cur的messages。- 严格按照调用层级Mock:
pyodbc.connect→ 连接对象 → 游标对象 → execute返回的游标实例。
内容的提问来源于stack exchange,提问作者vermachint
相关产品推荐
相关产品推荐

