[Python] Why did my mock test work with just a method instead of a full class?

Discussão em 'Python' iniciado por Stack, Março 11, 2025.

  1. Stack

    Stack Membro Participativo

    I always thought that you could mock a method on a class only when the class it is coming from is not instantiated in the code under test. And if it is you have to mock the class (just as you have to do for builtins).

    But today I made a "mistake" and saw that it just worked. So now I'm confused on when to use mocking a full class and when to use mocking a method on a class.

    Let's assume I have the following 3 example files:

    engine.py:

    class Engine(object):
    def __init__(self, start_temperature):
    self._started = False
    self._temperature = start_temperature

    def start(self):
    self._started = True
    self._set_temperature(10)

    def stop(self):
    self._started = False
    self._set_temperature(-10)

    def get_temperature(self):
    return self._temperature

    def _set_temperature(self, value):
    self._temperature += value


    MyClass.py:

    from Engine import Engine

    class MyClass(object):
    def __init__(self):
    self.engine = Engine(0)

    def check_start(self):
    self.engine.start()

    def check_stop(self):
    self.engine2 = Engine(1)
    self.engine2.stop()

    def get_temperature(self):
    return self.engine.get_temperature()


    and finally the actual test: test_MyClass.py:

    import unittest
    import unittest.mock as mock

    import MyClass

    class TestMyClass(unittest.TestCase):
    def test__initiation_returns_0_temperature(self):
    c = MyClass.MyClass()
    temperature = c.get_temperature()

    self.assertEqual(temperature, 0)

    @mock.patch("MyClass.Engine")
    def test_engine_get_temperature_mocked_via_class(self, mock_Engine_cls):
    mock_Engine_cls.return_value.get_temperature.return_value = 11

    c = MyClass.MyClass()
    c.check_start()
    temperature = c.get_temperature()

    self.assertEqual(temperature, 11)

    @mock.patch("MyClass.Engine.get_temperature")
    def test_engine_get_temperature_mocked_via_method(self, get_temperature_mock):
    get_temperature_mock.return_value = 12

    c = MyClass.MyClass()
    c.check_stop()
    temperature = c.get_temperature()

    self.assertEqual(temperature, 12)
    if __name__ == "__main__":
    unittest.main()


    I would have expected the 3rd test to error since in the past I got errors for instantiated classes if I did not mock the full class like done in the 2nd test case, but now it passes.

    Why is that?

    Continue reading...

Compartilhe esta Página