使用补丁模拟__init__,同时保留未修补的部分

时间:2017-11-20 19:28:57

标签: python unit-testing mocking patch

如何使用python中的Mocking模块使用@patch模拟类的echo -e "username\0password\0timestamp\0" \ | checkpassword-pam -s SERVICE \ --debug --stdout -- /usr/bin/id 3<&0 函数,如下所示:

这就是我的尝试:

__init__

输出

import mock
from mock import patch

class ConfigPortfolio(object):
    name = None
    def __init__(self, name=None, number=None):
        self.name = name
        self.number = number



with patch.object(ConfigPortfolio, 'name') as mock_name:
    mock_name.__get__ = mock.Mock(return_value='mocked name')
    # here I will call some functions in the actual prograam, where ConfigPortfolio will be instantied and I want to makre sure name will stay patched.
    p = ConfigPortfolio(name='hello', number=3) # will be deeply hidden in a function.
    print p.name # this should have changed to mocked name
    print p.number # this needs to stay 3 as it is instantiated with, as it is not overwritten by the wrapper.

patch.object不会更改名称,因为hello 3 会重新初始化在调用init之前修补的类属性。如何才能覆盖__init__

中设置的一个特定属性

在这种情况下的困难在于它是一个需要包装__init__并且可以用任何属性覆盖的类。当然后在实际测试中实例化类时(实例化将在代码深处发生,我无法控制它),它对我实例化它的值有用。这是我在补丁中设置的值,它将覆盖代码中的instantion值。

更新

我创建了一个包含 init 函数的新示例,并应该覆盖它的值。但目前它并没有这样做。任何有关修复它的建议都表示赞赏。

__init__

1 个答案:

答案 0 :(得分:1)

这里是解决方案:

import unittest
from mock import patch


class PortfolioConfig(object):
    ini_value = 10

    def __init__(self, maxtrades, name):
        self.maxtrades = maxtrades + 2
        self.name = name


class MREUnitTestBase(unittest.TestCase):
    @staticmethod
    def change_wrapper(class_to_wrap, override_constructor_properties=None, override_class_properties=None):
        method_to_wrap = class_to_wrap.__init__

        def wrapped(self, *args, **kwargs):
            for k, v in override_constructor_properties.items():
                kwargs[k] = v
            return method_to_wrap(self, *args, **kwargs)

        for k, v in override_class_properties.items():
            setattr(class_to_wrap, k, v)

        return wrapped


class PortfoloConfigTest(MREUnitTestBase):
    portfolio_override = {'maxtrades': 40}
    portfolio_override_properties = {'ini_value': 100}
    @patch.object(PortfolioConfig, '__init__', MREUnitTestBase.change_wrapper(PortfolioConfig, portfolio_override, portfolio_override_properties))

    def test_change_in_portfolio_config_by_test(self):
        p = program_run()  # running main program

        self.assertEqual(p.maxtrades, 42)  # was overridden by test
        self.assertEqual(p.name, 'hello')
        self.assertEqual(p.ini_value, 100)


# this is the program code
def program_run():
    p = PortfolioConfig(maxtrades=100, name='hello')
    return p