【发布时间】:2014-09-28 16:22:22
【问题描述】:
在 Python 中编写单元测试时模拟类或方法时,为什么需要使用 @patch 装饰器?我只是可以用没有任何补丁注释的 Mock 对象替换该方法。
例子:
class TestFoobar(unittest.TestCase):
def setUp(self):
self.foobar = FooBar()
# 1) With patch decorator:
@patch.object(FooBar, "_get_bar")
@patch.object(FooBar, "_get_foo")
def test_get_foobar_with_patch(self, mock_get_foo, mock_get_bar):
mock_get_bar.return_value = "bar1"
mock_get_foo.return_value = "foo1"
actual = self.foobar.get_foobar()
self.assertEqual("foo1bar1", actual)
# 2) Just replacing the real methods with Mock with proper return_value:
def test_get_foobar_with_replacement(self):
self.foobar._get_foo = Mock(return_value="foo2")
self.foobar._get_bar = Mock(return_value="bar2")
actual = self.foobar.get_foobar()
self.assertEqual("foo2bar2", actual)
谁能举个例子,补丁装饰器好,替换不好?
我们的团队一直使用补丁装饰器,但在阅读 this comment 的帖子后,我想到也许我们可以编写更好看的代码而不需要补丁装饰器。
我知道补丁是暂时的,所以在某些情况下,不使用补丁装饰器并用模拟替换方法是危险的吗?难道在一个测试方法中替换对象会影响下一个测试方法的结果?
我试图证明这一点,但结果是空的:两个测试都通过了下一个代码:
def test_get_foobar_with_replacement(self):
self.foobar._get_foo = Mock(return_value="foo2")
self.foobar._get_bar = Mock(return_value="bar2")
actual = self.foobar.get_foobar()
self.assertIsInstance(self.foobar._get_bar, Mock)
self.assertIsInstance(self.foobar._get_foo, Mock)
self.assertEqual("foo2bar2", actual)
def test_get_foobar_with_real_methods(self):
actual = self.foobar.get_foobar()
self.assertNotIsInstance(self.foobar._get_bar, Mock)
self.assertNotIsInstance(self.foobar._get_foo, Mock)
self.assertIsInstance(self.foobar._get_bar, types.MethodType)
self.assertIsInstance(self.foobar._get_foo, types.MethodType)
self.assertEqual("foobar", actual)
完整源代码(Python 3.3):dropbox.com/s/t8bewsdaalzrgke/test_foobar.py?dl=0
【问题讨论】:
标签: python unit-testing mocking decorator