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

如何在单元测试中Mock导入类实例方法内的open操作?

问题:Mock文件写入时mock_calls为空的排查方案

我需要测试自定义Builder类的build方法,该方法会将内容写入文件。为避免测试时实际创建文件,希望通过mock_open模拟写入过程,分析mock对象的call_args获取拟写入的内容。但编写model.py和test_model.py后,尝试多种patch目标,mock_calls始终为空,return_value.write.call_args返回None,请求排查问题。

原代码展示

model.py

class Builder:
    def __init__(self, input_template_map, output_filename, output_dir=""):
        self.input_template_map = input_template_map
        self.output_filename = output_filename
        self.output_dir = output_dir

    def build(self):
        output = ""
        # 一些读取文件生成output的代码
        with open(f"{self.output_dir}/{self.output_filename}.EB", "w") as f:
            f.write(output)

test_model.py

import unittest
from unittest.mock import mock_open, MagicMock, patch
from model import Builder

class ModelTest(unittest.TestCase): 
    @classmethod
    def setUpClass(cls):
        cls.builder = Builder({}, output_filename="test_out", output_dir="outputs")

    def test_build(self):
        m = mock_open()
        with patch("model.Builder.build.open", m, create=True):
            self.builder.build()
        print(m.mock_calls)
        print(m.return_value.write.call_args)

问题原因及解决方案

错误原因

你patch的目标路径错误。build方法中调用的open是全局内置函数,并非Builder.build方法的属性,所以patch("model.Builder.build.open")不会拦截到实际的open调用,导致mock对象没有任何调用记录。

正确解决方案

需要patchBuilder类所在模块(model)中的open引用,或者直接patch全局的builtins.open,推荐前者,避免影响其他测试用例。

修改后的test_build方法如下:

def test_build(self):
    m = mock_open()
    # 正确patch model模块中的open
    with patch("model.open", m):
        self.builder.build()
    # 打印所有mock调用记录
    print(m.mock_calls)
    # 获取write方法的调用参数
    print(m.return_value.write.call_args)
    # 可以添加断言验证写入内容
    m.return_value.write.assert_called_once_with("")

原理说明

Python的mock是基于在哪里被调用而不是在哪里定义来生效的。Builder.build方法在model模块中调用了open,所以需要patchmodel模块下的open引用,这样当build方法调用open时,会使用你提供的mock对象,从而记录下所有调用行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 01:11:20