gpt4 book ai didi

使用两个不同文件的类中的 Python 模拟内置 'open'

转载 作者:太空狗 更新时间:2023-10-29 17:44:02 25 4
gpt4 key购买 nike

当两个文件都使用上下文管理器时,我无法弄清楚如何模拟类中打开的两个文件。我知道如何使用像这样的模拟模块为一个上下文管理的文件执行此操作:

@patch('__builtin__.open')
def test_interface_mapping(self, mock_config):
m = MagicMock(spec=file)
handle = m.return_value.__enter__.return_value
handle.__iter__.return_value = ('aa', 'bb')

我的问题是当一个类在同一调用中打开两个不同的文件时如何执行此操作。在我的例子中,类 __init__() 将文件预加载到两个映射中。该类用于其他类。我想模拟这两个文件的加载以提供我的测试数据,以便可以根据我预加载的测试文件内容测试使用 IfAddrConfig 对象的其他类。

这是我正在努力处理的类的一个示例,它在 __init__() 中加载了两个文件,我想模拟这两个文件以加载我的测试注入(inject)文件内容。 getInterfaceMap() 是经常被调用的函数,所以我不希望它在每次调用时加载和解析文件,因此在 __init__() 中预加载 map 一次。

class IfAddrConfig(object):
def __init__(self):
# Initialize the static maps once since they require file operations
# that we do not want to be calling every time getInterfaceMap() is used
self.settings_map = self.loadSettings()
self.config_map = self.loadConfig()

def loadConfig(self):
config_map = defaultdict(dict)
with open(os.path.join('some_path.cfg'), 'r') as stream:
for line in stream:
# Parse line and build up config_map entries
return config_map

def loadSettings(self):
settings_map = {}
with open('another_path.cfg', 'r') as stream:
for line in stream:
# Parse line and build up settings_map entries
return settings_map

def getInterfaceMap(self, interface):
# Uses both the settings and config maps to finally create a composite map
# that is returned to called
interface_map = {}
for values in self.config_map.values():
# Accesss self.settings_map and combine/compare entries with
# self.config_map values to build new composite mappings that
# depend on supplied interface value
return interface_map

最佳答案

您必须使用修补后的 open 对象 (mock_open) 的 side_effect 属性,并且不要忘记设置 return_value 用于 __exit__ 方法。

@patch('__builtin__.open', spec=open)
def test_interface_mapping(self, mock_open):
handle1 = MagicMock()
handle1.__enter__.return_value.__iter__.return_value = ('aa', 'bb')
handle1.__exit__.return_value=False
handle2 = MagicMock()
handle2.__enter__.return_value.__iter__.return_value = ('AA', 'BB')
handle2.__exit__.return_value=False
mock_open.side_effect = (handle1, handle2)
with open("ppp") as f:
self.assertListEqual(["aa","bb"],[x for x in f])
with open("ppp") as f:
self.assertListEqual(["AA","BB"],[x for x in f])

[编辑]我找到了一种更优雅的方式来做到这一点 Mock builtin 'open" function when used in contextlib

所以你可以像这样重写测试

@patch('__builtin__.open', new_callable=mock_open, read_data="aa\nbb")
def test_interface_mapping_new(self, mo):
handlers = (mo.return_value,mock_open(read_data="AA\nBB").return_value,)
mo.side_effect = handlers
with open("ppp") as f:
self.assertEqual("aa\nbb",f.read())
with open("ppp") as f:
self.assertEqual("AA\nBB",f.read())

从 python 3.4 开始,您还可以使用 readline()、readlines() 而无需模拟任何其他内容。

关于使用两个不同文件的类中的 Python 模拟内置 'open',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26783678/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com