使用上下文管理器模拟open并获取open的参数

时间:2019-03-27 11:21:15

标签: python unit-testing mocking

首先,对不起,如果以前已经回答过,但是我一直到处都是,找不到任何东西。

我有一个执行此操作的功能(总结):

def func(path):
  with open(path) as f:
    json.load(f)

我想对其进行单元测试,我想当我使用open作为上下文管理器时,f是我传递给open的参数的名称。我遇到的问题是我无法在适当的模块中模拟enter方法,每次都会中断。到目前为止,这就是我正在做的事情:

def setUp(self):
    # Setup the content of the config files for the tests
    json.load = MagicMock(side_effect=file_content)

    # Opening a file returns the name of the file
    builtins.open = MagicMock(side_effect=lambda x: x) #1
    builtins.open.__enter__ = MagicMock(side_effect=builtins.open.return_value) #2

MagicMock数字1符合我的预期,当我运行open(“ test”)时,它返回“ test”。但是,我无法模拟 enter 来返回传递给我打开的所有内容,它总是失败,并显示AttributeError: __enter__。我也尝试过

builtins.open.return_value.__enter__ = MagicMock...

没有运气。谁能想到可以实现这一目标的方法?我已经看到了如何模拟魔术方法,并且我认为我对单元测试模拟感到满意,但是在这种情况下,我找不到合适的解决方案。谢谢!

1 个答案:

答案 0 :(得分:0)

我明白了!

我必须从动力学上定义side_effect,但似乎运行良好。这就是我所做的:

def setUp(self):
    # Setup the content of the config files for the tests
    json.load = MagicMock(side_effect=file_content)

    # Opening a file returns the name of the file
    def get_mock_context(filename):
        mock_context = MagicMock()
        mock_context.__enter__.return_value = filename
        mock_context.__exit__.return_value = False
        return mock_context
    builtins.open = MagicMock(side_effect=get_mock_context)

通过这种方式,返回值是一个模拟,它具有__enter____exit__方法,它们完全返回我传递给open调用的文件名。