Reputation: 775
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
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