kri*_*ild 7 python unit-testing mocking decorator
在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)
Run Code Online (Sandbox Code Playgroud)
有人可以提供一个例子,补丁装饰器是好的,替换是坏的吗?
我们总是在我们的团队中使用补丁装饰器,但在阅读了这篇帖子的评论之后,我认为可能我们可以编写更好看的代码而无需补丁装饰器.
我知道修补是暂时的,所以也许在某些情况下,不使用补丁修饰器并用mock替换方法是危险的?可能是在一个测试方法中替换对象会影响下一个测试方法的结果吗?
我试图证明这一点,但是空了:两个测试都传递到下一个代码中:
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)
Run Code Online (Sandbox Code Playgroud)
完整源代码(Python 3.3):dropbox.com/s/t8bewsdaalzrgke/test_foobar.py?dl=0
patch.object在测试方法返回后,将修补的项目恢复到其原始状态.如果您自己修补对象,则需要恢复原始值(如果该对象将在另一个测试中使用).
在您的两个示例中,您实际上修补了两个不同的东西.您的来电patch.object补丁的班 FooBar,而你的猴子补丁修补的特定实例的FooBar.
如果每次都从头开始创建对象,则恢复原始对象并不重要.(你没有表现出来,但我以为self.foobar是正在创建的setUp方法,所以,即使你更换了_get_foo方法,你不能重复使用特定的多个测试对象.)