简体   繁体   中英

Get patch'd object with use of unittest.mock's patch decorator and new

I have the below Python==3.8 code, where I:

  • Use unittest.mock.patch as a decorator
  • Preform a patch(..., new=...) :
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

Currently, this doesn't run, as the patched_Bar argument is not supplied. How can I get the patched_Bar arg to be passed in?

I know the below workaround exists, using with , but I prefer not to do this, as it's less clean in my opinion.

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

This is not needed, because you already have the patched class, eg Bar in your case. You get the same if you use the context manager, as you can see:

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

May be you are thinking about getting an instance of Bar instead, but that cannot work, because the instance will be created only inside the test.

The difference with a default mock is that you can set return_value to the mocked class, and each instantiation of the class will get you the same instance:

@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)

while with a replacement class which is not a mock this won't work:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM