Mock in Python: A Brief Explanation

Dipta Dwiyantoro
4 min readMay 23, 2021

In programming, we need to create a test to make sure our code works well when we use it. Sometimes we want to test a function but the function has interaction to other infrastructure such as doing an API Call to other server. We don’t know how to test it and because of that we don’t test that function and lose some code coverage in our code. It will cause no problem if your project is not huge. Handling a huge project is different. Each time we make a code, we need to test it to make sure our code works in the way that we think.

There is a way we resolve this problem. We can imitate and create a new definition of all dependencies that we use in that function. That technique is called “Mocking”.

Mocking

Mocking is other way in testing for imitating or creating a new definition of a function and change the function that are difficult to test, for example we mock a request function for an API Call. We can use this technique when we create a test for one function only (single responsibility test).

Mocking in Python

In Python, there is a mocking library called “mock”, we need to install the library using python pip if we want to use it by using this command

pip install mock

After you install it, you can use mock package by importing using this syntax

from unittest import mock

There are plenty useful mocking tools, in that library. But in this article i only discussed about “patch” decorator and “Mock” object.

“patch” decorator

“patch” is a decorator for create a mock object for imported package in the function that will be tested. For example :

//b.pydef fun1():
return "test"
//a.pyimport .b as bdef test1():
return b.fun1()
//test_a.pyfrom unittest import mock, TestCaseclass ATest(TestCase): @mock.patch("a.b")
def test_test1(self,b_mock: mock.Mock):

In that example, “patch” decorator is used to mock “b” package that imported by “a” package. The mock object will be passed through the test function and after that we can modify the behavior in that object. We can pass the decorator in the Test Class to make all test function in the class receive mock object from some function or package.

Mock Object

Mock object is an object that will imitate our function or package in our test. To create mock object, you can use “patch” decorator or you can instantiate it using this command

mock.Mock()

There are some core feature in this mock object.

  • Create a new object variable

You can instantiate new object variable by declaring it like existing variable

a = mock.Mock()
a.NEW_OBJECT = 'a'
a.NEW_OBJECT_1 = 'b'

You can try imitate package variables using this feature.

  • Design a new function

You can assign return value for each call to a mock function regardless the arguments.

a = mock.Mock()
a.func1.return_value = 'sd'
a.func1() #Ouput: sd
a.func1('a') #Output: sd

If you want to make a function that have different return value each call, you can use side_effect

a = mock.Mock()
a.func1.side_effect = [1,2,3]
a.func1() #1
a.func1() #2
a.func1() #3

You can assign a function that receive an arguments and return a value according to the argument

a = mock.Mock()
data = [1,2,3]
a.func1.side_effect = lambda x: data[x]
a.func1(0) #1
a.func1(2) #3

Besides that you can use this side_effect to raise an exception

a = mock.Mock()
a.func1.side_effect = Exception()
try:
a.func1()
except:
print('exc')
#Output: Exc
  • Variable in Mock is a Mock too

This feature can be useful if you have nested variable of an object to be mocked too.

a = mock.Mock()
a.package1.package2.test1 = 'a'
a.package1.package2.test1 #Return: a
  • Assert function call

Using this feature you can check the function that you create in the mock object is called or not.

a = mock.Mock()
a.func1.return_value = 'a'
a.func1.assert_called_once() #This will raise an error
//Other version
a.func1()
a.func1.assert_called_once()

You can see other assert in this link

Example Implementation

In this semester, me and my team build an app called Crowd+. In this app i implement aws s3 function testing using mock package and django TestCase, it make us easier to test because we don’t have to turn on internet access, prepare the upload file and clear the s3 server.

S3 Implementation
S3 Test

In this example, i tested s3 upload function. In the test file i create 4 mocks, there are settings, time.time, get_client, and s3_client. I use some of the core feature of the mock object such as

  • Create a new object variable in settings variable
  • Design a function in time package and get_client
  • Assert function call in upload_fileobj

--

--