You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在单元测试中Mock cx_Oracle的cursor.execute()以返回0行?

解决cx_Oracle单元测试Mock cursor.execute()的问题

错误原因

你遇到的TypeError: Need a valid target to patch. You supplied: 'cx_Oracle',是因为mock.patch的目标路径错误。直接patch顶层的cx_Oracle模块无效,必须patch你的业务代码模块中导入的cx_Oracle实例。假设你的业务代码文件名为dump_intexdb_n_load.py,正确的patch目标应该是dump_intexdb_n_load.cx_Oracle。

另外测试代码还存在两个问题:

  • 业务代码没有用上下文管理器(with语句)处理cursor,所以不需要设置__enter__返回值
  • 模拟cursor.execute.return_value = []无效,因为遍历cursor是靠它的迭代器,不是execute的返回值

修正后的测试代码

@mock.patch('dump_intexdb_n_load.cx_Oracle')  # 替换为你的业务代码模块名.cx_Oracle
def test_invalid_data(self, mock_cx_Oracle):
    print("Starting test : Test with data file having size < 100000")
    mock_cursor = mock.MagicMock()
    
    # 模拟execute执行成功(execute本身不返回查询结果,无需设置返回值为列表)
    mock_cursor.execute.return_value = None
    
    # 模拟cursor迭代返回空,即没有数据行
    mock_cursor.__iter__.return_value = iter([])
    
    # 模拟cursor.description,保证表头获取逻辑不报错,可根据实际查询字段调整
    mock_cursor.description = [('COLUMN1',), ('COLUMN2',)]
    
    # 关联连接与cursor:connect返回的connection调用cursor()得到mock_cursor
    mock_cx_Oracle.connect.return_value.cursor.return_value = mock_cursor

    with self.assertRaises(SystemExit) as cm:
       dump_intexdb_n_load.main()
    self.assertEqual(cm.exception.code, 1)

关键修改点说明

  1. 修正patch路径:把@mock.patch('cx_Oracle')改成@mock.patch('你的业务模块名.cx_Oracle'),确保mock的是业务代码里实际使用的cx_Oracle对象。
  2. 正确模拟cursor迭代:业务代码通过for row in cursor:遍历结果,所以需要让mock_cursor.__iter__.return_value返回空迭代器,模拟0行数据的情况。
  3. 处理cursor.description:如果业务代码需要获取表头,即使无数据行,cursor.description也需有字段信息(否则会抛出迭代None的错误),所以要设置模拟的字段列表。
  4. 移除不必要的__enter__设置:业务代码未使用with connection.cursor() as cursor:写法,无需设置__enter__返回值,直接让connection.cursor()返回mock_cursor即可。

内容的提问来源于stack exchange,提问作者Amruta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 05:55:48