Basic of Mocking Explained in Python

While writing the unit tests there are lot of instances when we would like to test the method which is calling third api’s  or having dependency on different methods.This article if for beginners, who want to start testing using mocking.

What is Mocking:

When you test a method(Called A) which has dependency on different methods (i.e. calling different methods) in that case instead of calling each method(used under method A), you mock those different method to simulate the behaviour instead of directly calling those methods. So the idea is to not call all the depend methods instead of that mock those method to test only method(A).

Here method could be internal build method, third party api method or python in built libraries.

Here is the example:

def testing_primary_method():
       a = second_method()     # Calling a method
       b = third_method()      # Calling a method
       return (a, b)            # return the result

On above example, you might not want to test only testing_primary_method() instead of calling second_method() and third_method().
so here it make sense to mock second_method() and third_method(). Mocking here solve the problem to not call these methods explicitly but simulate the behaviour(i.e. return value of methods).
There are different methods to perform mocking and patch(decorator) is widely use to mock methods or objects in python. We will go through basic mocking using mock library, covering all different mocking and different scenarios is out of scope of this article.So let’s start learning about the basic mocking and how to implement it.
There are different ways to implement mocking for different methods and classes. These are primarily the ways to mock:

  • Use a decorator when all of the code in your test function body uses a mock.
  • Use a context manager when some of the code in your test function uses a mock and other code references the actual function.
  • Use a patcher when you need to explicitly start and stop mocking a function across multiple tests (e.g. the setUp() and tearDown() functions in a test class).

Let’s start with a example, which we will use throughout the article to perform all above type of mocking:
Let’s say we have a method which calculate average income inside the company

def calculate_average_income(number_of_people):
       averate_income = 0
       # calling a method(could be external/build in)
       total_income = get_total_income(number_of_people)  
       return (total_income/number_of_people)

Above example(calculate_average_income method) is simple one where we are passing number of people and getting the total_income of all those people.
Here we don’t want to call get_total_income() method as it kind of unnecessary to test it as we only want to test calculate_average_income method.
Using Decorator:

 from mock import patch 
def test_get_average_income(mock_total_income):
      mock_total_income.return_value = 7896778;
      average_income = calculate_average_income(78908)
      AssertEqual(average_income, 7896778/78908)

Let’s understand, what we have done here to test the method:

  • Here we are mocking method ‘get_total_income’ and this is how you mock a method in while using patch decorator:
     @patch('', '')

    here would be name of method like ‘get_total_income’ OR ‘module1.get_total_income’.

  • We passed the parameter called (mock_total_income) which is parameter for mocked method.
  • We set the return value for mocked method which is kind of simulating the behaviour of get_total_income method
    mock_total_income.return_value = 7896778;
    We are setting the return value of the method and it’s necessary as we are expecting that method to perform some action(not actually) and return the response.
  • Asserting the result

Let’s explore other options:
Using Context Managers

 from mock import patch
def test_get_average_income():
      with mock.patch('get_total_income', return_value=7896778) as mock_total:
           average_income = calculate_average_income(78908)
           AssertEqual(average_income, 7896778/78908)

Using Mock Object

 from mock import patch
mock = Mock()
def test_get_average_income():
     mock.get_total_income.return_value = 78908
     average_income = calculate_average_income(78908)
     AssertEqual(average_income, 7896778/78908)

Other two examples are doing the same thing and easy to understand
However, if you would like to learn more about the mocking and what other ways we can achieve mocking. look up this python documents : Mocking Python Docs
Please leave the comments or email me for any questions. Happy Mocking!!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s