首页 > 解决方案 > 使用 unittest.mock 的补丁装饰器和 new 获取补丁对象

问题描述

我有以下Python==3.8代码,其中我:

from unittest.mock import patch

class Foo:
    pass

class Bar:
    pass

@patch(__name__ + f".Foo", new=Bar)
def test_foo(patched_Bar) -> None:
    _ = 0  # Do stuff

目前,这不会运行,因为patched_Bar没有提供参数。如何让patched_Bararg 传入?

我知道存在以下解决方法,使用with,但我不喜欢这样做,因为我认为它不太干净。

def test_foo2() -> None:
    with patch(__name__ + f".Foo", new=Bar) as patched_Bar:
        _ = 0  # Do stuff

标签: pythonmonkeypatchingpython-unittest.mock

解决方案


这不是必需的,因为您已经有了修补类,例如Bar在您的情况下。如果您使用上下文管理器,您会得到相同的结果,如您所见:

def test_foo() -> None:
    with patch(f"{__name__}.Foo", new=Bar) as patched_Bar:
        assert patched_bar == Bar

可能您正在考虑获取一个实例Bar,但这不起作用,因为该实例将仅在测试中创建。

与默认模拟的区别在于您可以设置return_value为模拟类,并且该类的每个实例化都会为您提供相同的实例:

@patch(f"{__name__}.Foo")
def test_foo(patched_foo) -> None:
    foo1 = Foo()
    foo2 = Foo()
    assert patched_foo.return_value == foo1 == foo2
    assert isinstance(foo1, MagicMock)

而对于不是模拟的替换类,这将不起作用:

@patch(f"{__name__}.Foo", Bar)
def test_foo() -> None:
    foo1 = Foo()
    foo2 = Foo()
    assert foo1 != foo2
    assert isinstance(foo1, Bar)


推荐阅读