What is the difference between mocking and monkey patching?

Monkey patching is replacing a function/method/class by another at runtime, for testing purpses, fixing a bug or otherwise changing behaviour. The unittest.mock library makes use of monkey patching to replace part of your software under test by mock objects. It provides functionality for writing clever unittests, such as: It keeps record of how mock objects … Read more

Can you monkey patch methods on core types in Python?

No, you cannot. In Python, all data (classes, methods, functions, etc) defined in C extension modules (including builtins) are immutable. This is because C modules are shared between multiple interpreters in the same process, so monkeypatching them would also affect unrelated interpreters in the same process. (Multiple interpreters in the same process are possible through … Read more

Monkey patching a @property

Subclass the base class (Foo) and change single instance’s class to match the new subclass using __class__ attribute: >>> class Foo: … @property … def bar(self): … return ‘Foo.bar’ … >>> f = Foo() >>> f.bar ‘Foo.bar’ >>> class _SubFoo(Foo): … bar = 0 … >>> f.__class__ = _SubFoo >>> f.bar 0 >>> f.bar = … Read more

Can you patch *just* a nested function with closure, or must the whole outer function be repeated?

Yes, you can replace an inner function, even if it is using a closure. You’ll have to jump through a few hoops though. Please take into account: You need to create the replacement function as a nested function too, to ensure that Python creates the same closure. If the original function has a closure over … Read more

How does one monkey patch a function in python?

It may help to think of how Python namespaces work: they’re essentially dictionaries. So when you do this: from a_package.baz import do_something_expensive do_something_expensive = lambda: ‘Something really cheap.’ think of it like this: do_something_expensive = a_package.baz[‘do_something_expensive’] do_something_expensive = lambda: ‘Something really cheap.’ Hopefully you can realize why this doesn’t work then 🙂 Once you import … Read more

Monkey patching a class in another module in Python

The following should work: import thirdpartymodule_a import thirdpartymodule_b def new_init(self): self.a = 43 thirdpartymodule_a.SomeClass.__init__ = new_init thirdpartymodule_b.dosomething() If you want the new init to call the old init replace the new_init() definition with the following: old_init = thirdpartymodule_a.SomeClass.__init__ def new_init(self, *k, **kw): old_init(self, *k, **kw) self.a = 43