在python中模拟对象的成员变量

时间:2016-07-06 07:32:45

标签: python unit-testing

我有以下python代码来测试

class Foo(object):
    def __init__(self):
        self.__fb_access_tokens = PropertiesReader('path/to/authentication_details/file')
        self.__fb_post_write_path = PropertiesReader('path/to/write_properties/file')

    def write_information(self):
        contents = compute_file_contents()
        write_contents_to_file(self.__fb_post_write_path, contents)

在我的测试用例中,我想模仿self.__fb_post_write_path。我无法模仿PropertiesReader(),因为它也会影响self.__fb_access_tokens

是否可以在python中模拟对象的成员变量?

任何建议都将受到高度赞赏。

谢谢!

1 个答案:

答案 0 :(得分:2)

只要您创建了该类的实例,就可以为该属性设置新值。你必须手动“破坏”#39;您选择使用双下划线名称的属性名称:

instance = Foo()
instance._Foo__fb_post_write_path = 'mocked value

请考虑使用单个下划线。除非您正在编写框架类(各种开发人员将子类化您的代码),否则您希望避免名称修改功能。

如果你必须拦截对PropertiesReader的调用,那么无论如何都要模拟PropertiesReader,但是对某些属性调用原始的未修补对象。将Mock.side_effect设置为函数并根据参数改变行为:

from module import PropertiesReader  # so you have access to the unpatched version

with mock.patch('module_under_test.PropertiesReader') as propreader_mock:
    def pr_side_effect(path):
        if path == 'path/to/authentication_details/file':
            return PropertiesReader(path)
        return mock.DEFAULT
    propreader_mock.side_effect = pr_side_effect

返回mock.DEFAULT告诉模拟回退到默认行为(例如,生成另一个Mock实例或生成您设置的return_value