我正在尝试使用Mock修补一些上下文管理器功能,因此我可以测试代码在给出好,坏和垃圾输入的情况下做出明智的事情。这是包含with
语句的测试代码。补丁在我的代码中的正确位置完成。
@patch("__main__.opened_w_error")
def test_get_recipe_file(self, mo):
mo.return_value = (Mock(), None)
mo.__enter__ = Mock(return_value=None)
mo.__exit__ = Mock(return_value=None)
with mo(…) as (fd, err): # AttributeError: __exit__ is raised here.
print(fd)
print(err)
然而,with mo(…) as (fd, err)
会引发AttributeError: __exit__
。
documentation for mocking magic methods表明您应该将其用作
with mo as (fd, err):
…
后面的代码是我试图嘲笑的。
但这不是我在代码中使用它的方式。对于那些真正感兴趣的人,我试图模仿处理打开文件和捕获错误的example 6 opened_w_error()
in PEP 343。因此代码是:
with open_w_error(filename, 'r') as (fd, err):
…
后者是我想要嘲笑的。
答案 0 :(得分:5)
请注意,传递给 with 语句的对象应该是__enter__
和__exit__
方法,并使用__enter__
的返回值对于as
构造。在您的情况下,您正在调用mo(...)
,它返回(Mock(), None)
,而这不是上下文管理器。您应该将此返回值移至__enter__
方法。
@patch("__main__.opened_w_error")
def test_get_recipe_file(self, mo):
mo.__enter__ = Mock(return_value=(Mock(), None))
mo.__exit__ = Mock(return_value=None)
with mo as (fd, err):
print(fd)
print(err)
编辑:如果您仍想调用mo
,请将其返回值设为上下文管理器。
@patch("__main__.opened_w_error")
def test_get_recipe_file(self, m_opened_w_error):
mo = Mock()
mo.__enter__ = Mock(return_value=(Mock(), None))
mo.__exit__ = Mock(return_value=None)
m_opened_w_error.return_value = mo
with m_opened_w_error(...) as (fd, err):
print(fd)
print(err)
答案 1 :(得分:1)
问题是当您正在调用mo(..)
时它返回的对象(tuple
)上没有__enter__
和__exit__
属性
要解决此问题,请将mo
分配给mo
return_value
,以便仍然可以找到您在其上设置的上下文管理器属性。
@patch("__main__.opened_w_error")
def test_get_recipe_file(self, mo):
mo.return_value = mo
mo.__enter__ = Mock(return_value=(Mock(), None))
mo.__exit__ = Mock(return_value=None)
with mo('file', 'r') as (fd, err):
print(fd)
print(err)
mo.assert_called_once_with('file', 'r') # Should be True
答案 2 :(得分:0)
你需要的是:
with mock.patch('__main__.opened_w_error') as mo:
mo.__enter__ = Mock(return_value=(Mock(), None))
mo.__exit__ = Mock(return_value=None)
# Your code goes here