如何在 python 中模拟针对特定路径打开的文件?
How do I mock a file open for a specific path in python?
所以我知道在我的单元测试中我可以模拟上下文管理器 open(),即:
with open('file_path', 'r') as stats:
嘲笑
with mock.patch('builtins.open', mock.mock_open(read_data=mock_json)):
但是有没有办法让我只针对特定的文件路径模拟它?或者也许有其他方法可以确保在单元测试中使用正确的路径调用上下文管理器?
要仅为特定路径模拟打开,您必须提供自己的模拟对象,该对象会根据路径以不同方式处理打开。假设我们有一些功能:
def do_open(path):
with open(path, "r") as f:
return f.read()
如果 path
是“bar”,open
将被模拟为 return 一个内容为“bar”的文件,但除此之外就像往常一样工作,你可以做一些事情像这样:
from unittest import mock
from my_module.do_open import do_open
builtin_open = open # save the unpatched version
def mock_open(*args, **kwargs):
if args[0] == "foo":
# mocked open for path "foo"
return mock.mock_open(read_data="bar")(*args, **kwargs)
# unpatched version for every other path
return builtin_open(*args, **kwargs)
@mock.patch("builtins.open", mock_open)
def test_open():
assert do_open("foo") == "bar"
assert do_open(__file__) != "bar"
如果您不想将原始 open
保存在全局变量中,您也可以将其包装到 class:
class MockOpen:
builtin_open = open
def open(self, *args, **kwargs):
if args[0] == "foo":
return mock.mock_open(read_data="bar")(*args, **kwargs)
return self.builtin_open(*args, **kwargs)
@mock.patch("builtins.open", MockOpen().open)
def test_open():
...
所以我知道在我的单元测试中我可以模拟上下文管理器 open(),即:
with open('file_path', 'r') as stats:
嘲笑
with mock.patch('builtins.open', mock.mock_open(read_data=mock_json)):
但是有没有办法让我只针对特定的文件路径模拟它?或者也许有其他方法可以确保在单元测试中使用正确的路径调用上下文管理器?
要仅为特定路径模拟打开,您必须提供自己的模拟对象,该对象会根据路径以不同方式处理打开。假设我们有一些功能:
def do_open(path):
with open(path, "r") as f:
return f.read()
如果 path
是“bar”,open
将被模拟为 return 一个内容为“bar”的文件,但除此之外就像往常一样工作,你可以做一些事情像这样:
from unittest import mock
from my_module.do_open import do_open
builtin_open = open # save the unpatched version
def mock_open(*args, **kwargs):
if args[0] == "foo":
# mocked open for path "foo"
return mock.mock_open(read_data="bar")(*args, **kwargs)
# unpatched version for every other path
return builtin_open(*args, **kwargs)
@mock.patch("builtins.open", mock_open)
def test_open():
assert do_open("foo") == "bar"
assert do_open(__file__) != "bar"
如果您不想将原始 open
保存在全局变量中,您也可以将其包装到 class:
class MockOpen:
builtin_open = open
def open(self, *args, **kwargs):
if args[0] == "foo":
return mock.mock_open(read_data="bar")(*args, **kwargs)
return self.builtin_open(*args, **kwargs)
@mock.patch("builtins.open", MockOpen().open)
def test_open():
...