5

I have a Python Clas with 2 methods.

The first, _getTemperature_() is protected and the second one is a public method. I have to write a unitTest but I have no clue, how to mock the protected method? I just found tutorials to mock a public method which is used at the test direct. But not in a method which sould be tested.

class StateOn(self):

    #Temperature in °C
    _target = 15

    # currrent Temperature by Sensor in °C
    def _getTemperature_(self):
        return valueFromSensorXY()


    def validateTemperature(self):
        if self._getTemperature_() >= self._target:
            return StateOff()

Does someone can give me a hint, or an explaination to find a solution about this issue?

michael-mammut
  • 2,595
  • 5
  • 28
  • 46
  • 2
    `def _getTemperature_()(self)` is not a valid syntax. There's no such thing called public and private, `_` is just a convention in Python and it doesn't change anything(it is special only in module imports). – Ashwini Chaudhary Aug 08 '17 at 00:02

3 Answers3

10

A bit late to the party, but here's an alternative method:

from unittest import mock

class MyClass():
    def __my_method(self):
        # Implement logic here...
        pass

def test_my_class():
    my_class = MyClass()
    my_class._MyClass__my_method = mock.Mock()
    # Run testing stuff...

By setting my_class._MyClass__my_method to mock.Mock() we effectively have a mock in place of the private method.

Note that we need to set my_class._MyClass__my_method and not my_class.__my_method, due to Python's name mangling of private attributes.

Renato Byrro
  • 3,578
  • 19
  • 34
2
def test_validate_temprature(self):
   state = StateOn()
   fake_temp = 15
   with mock.patch.object(state, '_StateOn__getTemperature_', return_value=fake_temp) as temp_mock:
       result = state.validateTemperature()
       self.assertIsInstance(result, StateOff)
       temp_mock.assert_called_once()
Chandan Kumar
  • 1,066
  • 10
  • 16
-1
fake_temp = 15
with mock.patch.object(StateOn, '_getTemperature', return_value=fake_temp) as mock_temp:
    result = StateOn().validateTemperature()
    self.assertIsInstance(result, StateOff)
Dan
  • 1,874
  • 1
  • 16
  • 21
  • thank you for your very fast reply with perfect input. I substitue the @ to `with` and added into an method. Thank you!! :) – michael-mammut Aug 08 '17 at 00:43
  • 11
    This solution does not actually seem to work for private methods. I get CLASS does not have the attribute __FUNCTION –  Mar 13 '19 at 16:32
  • 1
    @Corne private functions (functions starting with __function()) are obsfucated when a class is interpreted so they remain private. IE a function with the name __ex_function() may be assigned the name afsdlfkjasdfjasldjfasjdfasjdf() to make it private upon interpretation. – spencer.pinegar Sep 25 '19 at 22:25