0

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
Intrastellar Explorer
  • 3,005
  • 9
  • 52
  • 119

1 Answers1

0

This is not needed, because you already have the patched class, e.g. 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)

MrBean Bremen
  • 14,916
  • 3
  • 26
  • 46