Nitin Kumar
Nitin Kumar

Reputation: 775

Mocking member variable of an object in python

I have the following python code to test

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)

In my testcases I want to mock the self.__fb_post_write_path. I cannot mock PropertiesReader() as it will also effect self.__fb_access_tokens.

Is it possible to mock member variables of an object in python?

Any suggestions would be highly appreciated.

Thanks!

Upvotes: 2

Views: 6947

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1123680

Just set a new value for the attribute once you've created an instance of the class. You'll have to manually 'mangle' the attribute name as you've chosen to use double-underscore names:

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

Consider using single underscores instead. Unless you are writing framework classes (where a wide variety of developers will subclass your code), you want to avoid the name mangling feature.

If you must intercept the call to PropertiesReader, then mock PropertiesReader anyway, but pass through a call to the original unpatched object for certain attributes. Set Mock.side_effect to a function and vary behaviour based on the arguments:

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

Returning mock.DEFAULT tells the mock to fall back to the default behaviour (e.g. produce another Mock instance or produce the return_value you set).

Upvotes: 1

Related Questions