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

如何Mock多个pd.read_sql数据库调用并解决测试时No module named 'pd'报错

问题原因

unittest.mock.patch 接收的目标路径是Python模块的真实导入路径,你在测试代码里用pd作为pandas的别名属于当前测试文件的局部别名,mock模块找不到全局名为pd的模块,因此抛出ModuleNotFoundError。

解决方法

有两种可行的修正方式,二选一即可:

方式1:直接patch pandas原生的read_sql方法

把装饰器的路径改成pandas官方模块路径:

@mock.patch('pandas.read_sql')

方式2:patch业务代码中实际调用的pd.read_sql

如果你只想针对该业务模块的read_sql调用做mock,需要写你业务模块里pd.read_sql的完整导入路径,假设你的get_sql_queries函数定义在functions.get_transaction_data模块中,且该模块头部是用import pandas as pd导入的,就写成:

@mock.patch('functions.get_transaction_data.pd.read_sql')

修正后的完整测试代码示例

import unittest
from unittest import mock
import pandas as pd
from functions import get_transaction_data


class GetSQLQueriesTest(unittest.TestCase):
    # 这里修改为正确的patch路径
    @mock.patch('pandas.read_sql')
    def test_get_sql_queries(self, mock_read_sql):
        transaction_data = pd.DataFrame(columns=['Fund', 'Symbol'], data=[['Fund 1', 'Symbol 1']])
        mark_data = pd.DataFrame(columns=['Fund', 'Symbol'], data=[['Fund 2', 'Symbol 2']])

        mock_read_sql.side_effect = (transaction_data, mark_data)  # 调用顺序固定时可使用该写法

        output = get_transaction_data.get_transactions_between_two_dates()
        # 注意对比DataFrame要改用pandas自带的方法,直接用assertEqual会报错
        pd.testing.assert_frame_equal(output[0], transaction_data)
        pd.testing.assert_frame_equal(output[1], mark_data)

额外优化建议

如果你的函数中SQL查询顺序可能调整,用side_effect按顺序返回的方式不够稳妥,可以自定义判断逻辑匹配SQL语句返回对应值:

def mock_read_sql_side_effect(sql, con):
    if "sql_table" in sql:
        return pd.DataFrame(columns=['Fund', 'Symbol'], data=[['Fund 1', 'Symbol 1']])
    elif "other_sql_table" in sql:
        return pd.DataFrame(columns=['Fund', 'Symbol'], data=[['Fund 2', 'Symbol 2']])
    raise ValueError("未匹配到测试SQL")

mock_read_sql.side_effect = mock_read_sql_side_effect

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 20:18:03