Python单元测试-模拟与补丁

时间:2020-08-06 02:33:15

标签: python python-3.x python-unittest patch python-unittest.mock

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

  2. 何时使用mock.Mock()和何时使用mock.patch()

  3. 我已经读到,Mock用于替换当前作用域中使用的某些内容,而patch用于替换在另一个作用域中导入和/或创建的内容。有人可以解释什么意思吗?

  • 如果我们要在单独的测试文件中进行测试,那么是否会从dev / production文件中导入每个要测试的类方法,静态方法,实例方法?这是否意味着仅应在此处使用补丁?而且,如果我要在与要测试的代码相同的文件上进行测试,则首选使用模拟吗?正确吗?

1 个答案:

答案 0 :(得分:1)

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

from unittest.mock import patch

@patch('some_module.some_object')
def test_something(mocked_object):
    print(mocked_object)

这给出了类似的内容:

<MagicMock name='some_object' id='1870192381512'>

这等同于:

def test_something():
    with patch('some_module.some_object') as mocked_object:
        print(mocked_object)

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

引用文档:

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

您还可以手动创建Mock对象,并将其分配给对象-我想这就是您在问题中的意思。如果您执行此操作而不是使用patch,则有责任自己重置以前的状态。由于这更容易出错,因此我会建议使用专用的修补方法。

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

@mock.patch('my_functions.MyClass')
def test_object(mock_class):
    arg1 = Mock()
    arg2 = Mock()
    do_something(arg1, arg2)

    # check that do_something creates MyClass with the given arguments 
    mock_class.assert_called_with(arg1, arg2)

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

总结:

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