我正在尝试测试我拥有的将输出写入文件的类中的方法。但是,为了防止测试方法实际写入新文件,我想模拟写出过程并分析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的不同命名空间以及许多被问到的堆栈溢出问题,但我觉得我错过了一些东西。任何帮助将不胜感激!
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
在我的测试中有效。