使用mock.Mock() 与mock.patch() 有什么区别,以及何时使用其中之一?

Ren*_*aby 9 python patch python-3.x python-unittest python-unittest.mock

  1. mock.Mock()使用vs 和有什么区别mock.patch()

  2. 何时使用mock.Mock()以及何时使用mock.patch()

  3. 我读过 Mock 用于替换当前作用域中使用的内容,而 patch 用于替换在另一个作用域中导入和/或创建的内容。有人能解释一下这是什么意思吗?

  • 如果我们在单独的测试文件中进行测试,那么不是每个被测试的类方法、静态方法、实例方法都会从开发/生产文件中导入吗?这是否意味着这里应该只使用补丁?如果我要在与正在测试的代码相同的文件上进行测试,最好使用模拟?那是对的吗?

MrB*_*men 17

我不完全确定我是否理解你的问题,但我会尝试一下。如文档中所述,Mock对象(实际上是MagickMock实例)是使用patch装饰器创建的:

from unittest.mock import patch

@patch('some_module.some_object')
def test_something(mocked_object):
    print(mocked_object)
Run Code Online (Sandbox Code Playgroud)

这给出了类似的东西:

<MagicMock name='some_object' id='1870192381512'>
Run Code Online (Sandbox Code Playgroud)

这相当于:

<MagicMock name='some_object' id='1870192381512'>
Run Code Online (Sandbox Code Playgroud)

这使您可以用模拟对象替换任何对象,以避免调用实际的生产代码和/或检查原始对象的调用方式(如果该对象是函数)。首选使用(或某些类似方法)的原因patch是,这可以确保在测试之后(或在第二种情况下在上下文管理器范围之后)恢复补丁,因此对其他测试或其他代码没有副作用。

引用文档:

补丁装饰器仅用于在它们装饰的函数范围内修补对象。即使出现异常,它们也会自动为您处理取消补丁的操作。所有这些函数也可以在 with 语句中使用或用作类装饰器。

您还可以Mock手动创建一个对象并将其分配给一个对象 - 我认为这就是您在问题中的意思。如果您这样做而不是使用patch,您有责任自行重置之前的状态。由于这更容易出错,如果可能的话,我建议使用专用的修补方法。

这在本地对象和其他模拟中并不重要。很少需要模拟本地对象,但Mock实例通常与修补对象一起创建,以保留模拟对象的实例以供以后检查:

def test_something():
    with patch('some_module.some_object') as mocked_object:
        print(mocked_object)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,该 case 将仅用作模拟对象的参数,因此不需要重置。

总结一下:

  • patch是一个方便的装饰器/上下文管理器功能,用于用模拟对象(或其他对象)替换对象,并在完成后或发生异常时重置先前的状态
  • Mock或派生对象由 创建mock.patch,也可以手动创建。手动创建的模拟通常仅用于修补本地函数或其他不需要重置的模拟。

  • 谢谢您的回答!该网站上有很多旧答案说“Mock”优于“patch”,但没有提及原因。也许这就是 python2 的老智慧?当前的单元测试文档似乎建议您上面所说的:补丁优于模拟(尽管界面更奇怪;模拟更易于使用) (4认同)