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

pytest使用mark.parametrize做mocker.patch时复用前次mock数据问题

问题原因

该现象是Python可变对象的引用传递特性导致的,和pytest、mock工具的逻辑无关,属于完全符合预期的正常行为。
你定义的mock_data_1是pandas DataFrame类型,属于可变对象,两次参数化传入的都是同一个对象的内存引用。第一次测试运行时,业务代码直接在该对象上新增了列,修改了原始对象的内容,第二次测试拿到的自然就是被修改后的对象。
pytest的参数化不会自动对传入的可变对象做深拷贝,mock的return_value也只会原样返回你传入的对象,不会主动生成副本。

解决方案

不需要修改业务代码的前提下,测试侧可以通过以下几种方式解决:

  • 参数化时每次传入全新的DataFrame实例,不要复用同一个可变对象:
    @pytest.mark.parametrize(
        'mock_arguments, arg, result',
        [
            (pd.DataFrame({"col_1": [1,2,3]}), arg_1, output_1),
            (pd.DataFrame({"col_1": [1,2,3]}), arg_2, output_2)
        ]
    )
    
  • 定义mock数据为工厂函数,每次调用返回新的实例,patch时用side_effect动态返回副本:
    # 测试类内定义
    def mock_data_factory(self):
        return pd.DataFrame({"col_1": [1,2,3]})
    
    # 测试用例内patch修改为
    mocker.patch(
        'file.GetData.get_data',
        side_effect=lambda *args: self.mock_data_factory()
    )
    
  • 将mock数据定义为函数级fixture,每次测试用例运行自动生成新实例:
    @pytest.fixture(scope="function")
    def mock_data(self):
        return pd.DataFrame({"col_1": [1,2,3]})
    
补充说明

如果业务逻辑本身就不应该修改上游接口返回的原始数据,那在业务代码中加.copy()也是合理的优化方案,不属于为了适配测试的不合理修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 04:45:05