是否有一种简洁的方法来修补对象,以便您assert_call*
在测试用例中获得帮助程序,而无需实际删除操作?
例如,如何修改该@patch
行以获得以下测试传递:
from unittest import TestCase
from mock import patch
class Potato(object):
def foo(self, n):
return self.bar(n)
def bar(self, n):
return n + 2
class PotatoTest(TestCase):
@patch.object(Potato, 'foo')
def test_something(self, mock):
spud = Potato()
forty_two = spud.foo(n=40)
mock.assert_called_once_with(n=40)
self.assertEqual(forty_two, 42)
我可能会一起使用side_effect
,但是我希望有一种更好的方法可以在所有函数,类方法,静态方法,未绑定方法等上以相同的方式工作。
发布于 2018-12-19 08:33:02
与您的类似解决方案,使用wraps
:
def test_something(self):
spud = Potato()
with patch.object(Potato, 'foo', wraps=spud.foo) as mock:
forty_two = spud.foo(n=40)
mock.assert_called_once_with(n=40)
self.assertEqual(forty_two, 42)
根据文件:
wrap:要包装的模拟对象的项。如果wrap不是None,那么调用Mock会将调用传递给包装对象(返回实际结果)。模拟器上的属性访问将返回一个Mock对象,该对象包装了包装对象的相应属性(因此,尝试访问不存在的属性将引发AttributeError)。
class Potato(object):
def spam(self, n):
return self.foo(n=n)
def foo(self, n):
return self.bar(n)
def bar(self, n):
return n + 2
class PotatoTest(TestCase):
def test_something(self):
spud = Potato()
with patch.object(Potato, 'foo', wraps=spud.foo) as mock:
forty_two = spud.spam(n=40)
mock.assert_called_once_with(n=40)
self.assertEqual(forty_two, 42)
发布于 2018-12-19 09:34:00
这个答案解决了用户Quuxplusone的赏金中提到的额外要求:
对我的用例来说重要的是它可以使用
@patch.mock
,即它不需要我在构造Potato
(spud
在这个例子中)的实例和我的调用之间插入任何代码spud.foo
。我需要从一开始就使用模拟方法spud
创建foo
,因为我无法控制spud
创建的位置。
使用decorator可以毫不费力地实现上述用例:
import unittest
import unittest.mock # Python 3
def spy_decorator(method_to_decorate):
mock = unittest.mock.MagicMock()
def wrapper(self, *args, **kwargs):
mock(*args, **kwargs)
return method_to_decorate(self, *args, **kwargs)
wrapper.mock = mock
return wrapper
def spam(n=42):
spud = Potato()
return spud.foo(n=n)
class Potato(object):
def foo(self, n):
return self.bar(n)
def bar(self, n):
return n + 2
class PotatoTest(unittest.TestCase):
def test_something(self):
foo = spy_decorator(Potato.foo)
with unittest.mock.patch.object(Potato, 'foo', foo):
forty_two = spam(n=40)
foo.mock.assert_called_once_with(n=40)
self.assertEqual(forty_two, 42)
if __name__ == '__main__':
unittest.main()
如果替换的方法接受在测试下修改的可变参数,则可能希望初始化CopyingMock
代替MagicMock在
spy_decorator内部。
https://stackoverflow.com/questions/-100006318
复制相似问题