如何在测试方法中模拟受保护/私有方法?

5

我有一个Python类,其中包含两个方法。

第一个方法 _getTemperature_() 是受保护的,第二个方法是公共方法。我需要编写一个单元测试,但我不知道如何模拟受保护的方法?我只找到了关于如何模拟在测试中直接使用的公共方法的教程,但没有关于要测试的方法中如何模拟的教程。

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()

有人能给我一个提示或解释,帮我找到解决这个问题的方法吗?


2
def _getTemperature_()(self) 不是有效的语法。Python 中没有所谓的公共和私有,下划线 _ 只是一种约定,并不会改变任何东西(只在模块导入中才有特殊意义)。 - Ashwini Chaudhary
3个回答

10

虽然有点晚了,但这里提供一种替代方法:

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...

通过将my_class._MyClass__my_method设置为mock.Mock(),我们有效地在私有方法的位置放置了一个模拟。
请注意,由于Python对私有属性进行名称混淆(name mangling),我们需要设置my_class._MyClass__my_method而不是my_class.__my_method

2
上帝保佑您,先生。我已经在这个问题上奋斗了3天了 :) - swateek
有没有一种方法可以断言调用某个方法的内容? - Olivér Palotás
@OlivérPalotás 是的,你可以查看 unittest 和 Mock 文档 - hfc

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()

-1
fake_temp = 15
with mock.patch.object(StateOn, '_getTemperature', return_value=fake_temp) as mock_temp:
    result = StateOn().validateTemperature()
    self.assertIsInstance(result, StateOff)

非常感谢您的快速回复和完美的输入。我将@替换为“with”并添加到一个方法中。谢谢! :) - michael-mammut
11
这种解决方法似乎并不适用于私有方法。我收到了“CLASS没有__FUNCTION__属性”的错误提示。 - user2229108
1
@Corne 私有函数(以__function()开头的函数)在类被解释时会被混淆,因此它们保持为私有。例如,一个名为__ex_function()的函数可以被赋予名称afsdlfkjasdfjasldjfasjdfasjdf(),以在解释时使其成为私有。 - spencer.pinegar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接