在用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)
有人能举例说明补丁装饰器好而替换不好吗?
我们一直与团队一起使用补丁装饰器,但是在阅读了这篇评论后,我想到也许不需要补丁装饰器就可以编写看起来更好的代码。
我知道补丁是临时的,因此在某些情况下,不使用补丁装饰器而用模拟代替方法是危险的吗?难道在一种测试方法中替换对象会影响下一测试方法的结果吗?
我试图证明这一点,但是空了:两个测试都通过了下一个代码:
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
patch.object
测试方法返回后,将修补的项目恢复到原始状态。如果您自己对对象进行猴子修补,则如果该对象将在其他测试中使用,则需要恢复原始值。
在您的两个示例中,您实际上是在修补两个不同的事物。您对呼叫patch.object
补丁类 FooBar
,而你的猴子补丁修补的特定实例的FooBar
。
如果每次都会从头开始创建对象,则还原原始对象并不重要。(您没有显示它,但是我假设self.foobar
它是在一个setUp
方法中创建的,因此即使您替换了它的_get_foo
方法,也不会在多个测试中重用该特定对象。)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句