mock_open 用于在导入类的实例方法内部调用 open

问题描述 投票:0回答:1

我正在尝试测试我拥有的将输出写入文件的类中的方法。但是,为了防止测试方法实际写入新文件,我想模拟写出过程并分析mock()对象的call_args(即会写出的内容)。我知道我可以分析文件输出,但我觉得这种方式更干净,我想了解我在这里做错了什么,以提高我的单元测试技能。

我有 2 个文件,model.py 和 test_model.py。

模型.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 = ""
        # some code that adds to the 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)

但是,mock_calls 肯定是空的,并且 return_value.write.call_args 不返回任何内容。我已经尝试了我能想到的补丁第一个参数的所有可能目标...包括 test_model.Builder.build.open、test_model.Builder.open、model.Builder.open 等,结果相同。尽管我阅读了关于mock_open的文档、unittest.mock的不同命名空间以及许多被问到的堆栈溢出问题,但我觉得我错过了一些东西。任何帮助将不胜感激!

python python-3.x mocking python-unittest
1个回答
0
投票

mock_open()
返回的模拟对象用于
open
的上下文管理器。要处理对
open()
生成的文件对象的模拟调用,请调用模拟本身。这是一个传递并正确打印 write 调用的示例:


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("builtins.open", m):
            self.builder.build()

        # checking that the open call was as expected
        m.assert_called_with("outputs/test_out.EB", "w")

        # checking that the write call was as expected
        handle = m()
        handle.write.assert_called_once_with("")

        print(handle.mock_calls)

不要使用

m.return_value
,而是使用
m()
builtins.open
在我的测试中有效。

© www.soinside.com 2019 - 2024. All rights reserved.