## Python's Monkey Patch for Dummies

Alright, I’m going to cut to the chase here. I’m having problems with Monkey patching in Python and I want to make it clear for myself and anybody who might stumble upon my post in the future. So, what’s the big deal here?

Let’s say you have a model

And you have a Phonebook class that’s trying to access the database

Now, we know that get_name is accessing some database and we don’t want that to happen in unit test. We would like to stub that.

Coming from Java, I’d write my test like this.

It makes sense right? I want to stub something from models.person.get_name so I’m telling mock to stub that class but my test failed miserably.

Why? Because patch behaves differently than what we expected. This is explained in Where to patch. I’m going to summarize for you. Basically, patch is going to take effect from where it is looked up… For me after reading that I’m still confused. I might be the only one who’s confused here so I’m going to continue writing.

If we take a closer look how import behaves in Python, it would be clearer.

The line says please import get_name to the namespace in models/phonebook.py. So, when we want to use it we can just called get_name() without having to write models.person.get_name() Now if you change your code to be

You test would pass. Because now our Phonebook is looking up models.person.get_name namespace instead of having function get_name being imported to its namespace.

Now if you want the old test to work, your patch has to be changed to

That’s it for now. If you’re wondering why this is the case then looking at the source code of patch would help a lot. It’s using __import__ function.

Oct 25th, 2015