I write a lot of unit tests. Unfortunately, my code often requires monkey patching to be properly unit tested. I frequently use the patch
function from Michael Foord’s mock library (now available in Python 3.4 as unittest.mock) to monkey patch my code.
While chatting with other users of patch
, I realized that everyone seems to have their own favorite way to use it. In this post I will discuss the ways I use patch.
Decorator
patch can be used as a method decorator:
1 2 3 4 5 6 7 8 |
|
or as a class decorator:
1 2 3 4 5 6 7 8 |
|
I use patch as a decorator when I have a function I want patched during my whole test. I tend not to use patch as a class decorator and I’ll explain why below.
Context Manager
patch can be used as a context manager:
1 2 3 4 5 6 7 8 |
|
I prefer to use patch as a context manager when I want to patch a function for only part of a test. I do not use patch as a context manager when I want a function patched for an entire test.
Manually using start and stop
patch can also be used to manually patch/unpatch using start
and stop
methods:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
I prefer to use patch using start/stop when I need a function to be patched for every function in a test class.
This is probably the most common way I use patch in my tests. I often group my tests into test classes where each method is focused around testing the same function. Therefore I will usually want the same functions/objects patched for every test method.
I noted above that I prefer not to use class decorators to solve this problem. Instead, I prefer to use test class attributes to store references to patched functions instead of accepting patch arguments on every test method with decorators. I find this more DRY.
Warning: One of the primary benefits of the decorator/context manager forms of patch is that they handle clean up for you. Whenever you call start
to setup your patch object, always remember to call stop
to clean it up. Otherwise you’ll have a monkey patched function/object for the rest of your running program.
Summary
Patch can be used:
- as a method or class decorator
- as a context manager
- using start and stop methods
I prefer my tests to be readable, DRY, and easy to modify. I tend to use start/stop methods for that reason, but I also frequently use patch method decorators and sometimes use patch context managers. It’s useful to know the different flavors of patch
because your favorite flavor may not always be the most suitable one for the problem at hand.
Did I miss a flavor? Want to let me know which flavor you prefer and why? Please comment below.