Python unittest : to mock. patch() 或者只是用 Mock 替换方法?

标签 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)

谁能举个例子,patch decorator 好而 replacing 不好?

我们的团队一直在使用补丁装饰器,但在阅读 this comment 之后对于一篇文章,我想到也许我们可以在不需要补丁装饰器的情况下编写更漂亮的代码。

我知道打补丁是暂时的,所以在某些情况下,不使用补丁装饰器并用 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)

完整源代码(Python 3.3):dropbox.com/s/t8bewsdaalzrgke/test_foobar.py?dl=0

最佳答案

patch.object 将在测试方法返回后将您修补的项目恢复到其原始状态。如果您自己对对象进行猴子修补,如果该对象将在另一个测试中使用,则需要恢复原始值。

在你的两个例子中,你实际上是在修补两个不同的东西。您对 patch.object 的调用会修补 class FooBar,而您的猴子补丁会修补 的特定实例>FooBar.

如果每次都从头开始创建对象,那么恢复原始对象并不重要。 (你没有显示它,但我假设 self.foobar 是在 setUp 方法中创建的,所以即使你替换了它的 _get_foo 方法,您不会在多个测试中重用该特定对象。)

关于Python unittest : to mock. patch() 或者只是用 Mock 替换方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26086980/

相关文章:

python - 用python解析网站

java - 通过调用数据库来 stub /模拟方法的问题

c++ - 单元测试析构函数?

java - 如何使用 jMockit 和 TestNG 在最终类中验证对静态方法的调用?

Scala:模拟和蛋糕模式

ruby-on-rails - Rspec: Controller 中的 stub 方法

python - Nginx + Gunicorn + Flask --> 使用 X 小时后常有 500 个错误

python - 为什么在 Python 3 的 'sys.modules' 中没有导入模块?

python - 如何将矩阵保存在txt文件中,然后在python中将其作为矩阵再次打开?

scala - 单元测试异步 Scala 代码