Mocking with Python - Part I
Kiran Koduru • Apr 5, 2017 • 7 minutes to read • Last Updated: Nov 2, 2017If you have been following my blog, you may have noticed a pattern; I write a lot about testing software. Recently, I picked up a book on Building Micro Services, where I came across a chapter on testing micro services. This post is about mocking your python code to make it easier to test your micro services or the likes.
There are a lot of posts to describe the need for mocking. I won’t be getting into that discussion, though I do want to help you get started with mocking functions and objects in python. I found that when I tried to learn about mocking, there weren’t a lot of introductory tutorials for new comers and this blog post is a reflection of what I think might be useful to learn mocking.
Let’s start with a basic example where you fetch some rows of data from a database. If you were to write some python code for it, you will start by making a database connection through a ORM like SQLAlchemy. Once the connection is established, you will write SQL queries using the database object models. For the sake of simplicity, I will keep the code contained to:
- get_all_users(): A function with returns a iterable object of
users
in the database - has_user_expired(): A function which returns a
boolean
if the user has expired - find_expired_users(): A function which returns a
list
of expired user IDs in our database
For our test case we will use the python unittest framework. Each user
returned by get_all_users()
item is a SQLAlchemy object with the attributes id
, firstname
, lastname
, join_date
and expiration_date
.
Here’s how our application is structured. It contains just 3 files db_connection.py, app.py and test_app.py.
. ├── app.py # applicaton code ├── db_connection.py # database connection └── test_app.py # unit tests 0 directories, 3 files
This is what our application code looks like
We will write our test in the test_app.py file. We will use mocks to avoid querying the database to fetch records via get_all_users()
. For this we create a Mock
object and assign it the attributes that a user has. This Mock
object is just another python class when called for any fake attribute will return an answer.
It’s like a magic hat. You ask it for a variable, function, method etc. it returns a definite answer. You can also override the variable, function, method yourself so you know what is the expected result.
In our case we will override the SQLAlchemy database object user
and it’s attributes id
, firstname
, lastname
, join_date
and expiration_date
. So we can test for the user
object even though we know it’s not real.
Hope that gives you an idea of how to get started with mocking in python. A good practice is to run regular integration tests on the mocked data regularly. It’s possible that though your tests pass the moment you have production data your website begins to crumble. Hence the integration tests keep a tab on your unknowns.
I am writing a book!
While I do appreciate you reading my blog posts, I would like to draw your attention to another project of mine. I have slowly begun to write a book on how to build web scrapers with python. I go over topics on how to start with scrapy and end with building large scale automated scraping systems.
If you are looking to build web scrapers at scale or just receiving more anecdotes on python then please signup to the email list below.