Skip to content

Instantly share code, notes, and snippets.

@paul-butcher
Created June 16, 2021 08:12
Show Gist options
  • Save paul-butcher/43570671955f5602e53444387c29278b to your computer and use it in GitHub Desktop.
Save paul-butcher/43570671955f5602e53444387c29278b to your computer and use it in GitHub Desktop.
Demonstration of patching python methods whilst leaving the rest of the class intact.
from unittest import mock
class MyClass:
def __init__(self):
print('hello')
self.my_property = 'dolly'
def do_something(self):
print('world')
def do_something_else(self):
print(self.my_property)
def do_yet_another_thing(self):
print(f"goodbye {self.do_something()}")
print('exercise the class normally:')
o = MyClass()
o.do_something()
o.do_something_else()
o.do_yet_another_thing()
print('\nexercise the patched class:')
with mock.patch.object(MyClass, '__init__', return_value=None):
# Note that it does not say "hello" at this point
o2 = MyClass()
# Here, it prints "world"
o2.do_something()
# If the real function you are exercising relies on
# properties set in __init__, you will have to
# set them here instead.
o2.my_property = "Is it me you're looking for"
o2.do_something_else()
# You can patch any methods.
# Using the context manager means that the patch disappears
# when no longer in scope
with mock.patch.object(MyClass, 'do_something', return_value="banana"):
o2.do_yet_another_thing() # goodbye banana
o2.do_yet_another_thing() # goodbye None
@paul-butcher
Copy link
Author

Another note:

class MyClass:
...
    def do_yet_another_thing(self):
        o = MyOtherClass()
        print(f"{o.do_something()} {self.do_something()}")


class MyOtherClass:
    def do_something(self):
        return 'goodbye'

# If you are calling another class, you can mock out the constructor
# as though a function, but it's a bit more clunky, so you may be better off patching the 
# __init__ and the method you are calling.
with mock.patch('patching.MyOtherClass') as mocked:
    mocked.return_value.do_something.return_value = 'farewell'
    o2.do_yet_another_thing()  # farewell None

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment