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
.