I have a class that contains another class in a variable. Now I want to write a unit-test and define a mock object. Therefore I define a fixture in conftest.py and monkeypatch it with the mock object. I now get a the desired mock object but the inner object is noch the mock object which I defined. The problem ist that my mock that I have created in the fixture (so that the mock returns “Bye”) will not be applied. How can I fix this and is there any better solution? See my minimal example below:
module_a.py
class Connection:
def get(self, name):
return f"Hello {name}"
utils.py
from main.module_a import Connection
class Util:
def __int__(self):
self.conn: Connection = Connection()
module_main.py
from main.utils import Util
def main() -> str:
util: Util = Util()
msg: str = util.conn.get(name="Joe")
return msg
conftest.py
from unittest.mock import Mock
import pytest
from main.module_a import Connection
from main.utils import Util
@pytest.fixture(scope="function")
def util_mock(monkeypatch):
conn_mock: Mock = Mock(spec=Connection)
conn_mock.get.return_value = "Bye"
util_mock: Mock = Mock(spec=Util, conn=conn_mock)
monkeypatch.setattr(target="main.module_main.Util", name=util_mock)
return util_mock
test_module_main.py
from unittest.mock import Mock
from main import module_main
def test_main(util_mock: Mock):
msg: str = module_main.main()
test: str = util_mock.conn.get(name="foot")
assert test == "Bye" # work right afer fixture insertion
assert msg == "Bye" # fails after a new object is created
Advertisement
Answer
Found a solution myself. When a new object is created (Util()
) __call__ is triggered and returns a new object of the mock, hence all defined properties are lost. We just need to return the mock object itself with util_mock.return_value = util_mock
.