Testing is one of the most crucial phases before the deployment of an application. A developer usually has to test all the attributes and methods of an application before deeming it fit for use. Sometimes, the complex structure of the program or unpredictable dependencies can make it hard to make tests for the intended program.
To solve this issue, Python has introduced mocking. A mock object is used to control the behavior of the real objects, which are difficult to include in the test. The mock object imitates these real objects to make the testing easier, more efficient, and faster. There are multiple scenarios where it might be useful to use a mock object:
For Python versions Python3.3 and up,
unittest.mock
is the mock library. For older versions, you’ll need to install the mock library usingpip
.
pip install mock
unittest.mock
You can import the library in the following manner:
from unittest.mock import Mock
Moving forward, you can make a mock object to imitate any other object in your program. To do this, initialize a variable with Mock()
:
my_mock = Mock()
You can use the my_mock
object as an argument to a function or to redefine an object:
fun(my_mock)
real_obj = my_mock
When you do this, your mock object behaves precisely like the real_object. You can call all the functions and attributes of your real object(real_obj
) using your mock object(my_mock
):
my_mock.doThis()
my_mock.doThat(arg1, arg2, arg3)
There are two caveats to keep in mind when using mock methods:
To inspect if the methods are working correctly, the mock library allows us the assert the functions called using mock objects. There are four types of assertions:
.assert_called()
.assert_called_once()
.assert_called_with()
.assert_called_once_with()
.assert_called()
is used to check if the method is executed; whereas, .assert_called_once()
is used if the method is only executed one time..assert_called_with()
is used to check if the method is called with a particular set of arguments..assert_called_once_with()
is used to check if the method is called with a particular set of arguments.The mock library also lets you analyze how the object method is performed by using some particular methods:
.call_count
.call_args
.call_args_list
.method_calls
.call_count
is used to see how many times the method is called..call_args
tells the arguments used when the method is called..call_args
gives a list of arguments given to the call method call..method_calls
lists the methods called to the real_obj
library.Below is a simplified example to demonstrate how a mock object works.
from unittest.mock import Mockimport pandas as pdmy_mock = Mock()my_df = my_mock.DataFrame([["carnivore", "shark"],["carnivore", "lion"],["herbivore", "goat"],["herbivore", "sheep"]],columns = ["type", "name"])print(my_df)my_df.set_index("type", inplace=True)print(my_df.set_index.assert_called_with("type", inplace=True))print(my_df.set_index.call_count)print(my_df.set_index.call_args)
In this example, a Pandas my_mock
object. The mocked data frame is then assigned to the my_df
variable. my_df
now mimics the real object and can use all the functions of the real object.
.set_index()
method is called with argument "type, inplace=True"
.
To check if the method was executed correctly, the .assert_called_with()
method is used. Since the object is called with the same arguments as mentioned in the .asser_called_with()
statement, the output is None. In the case that the arguments did not match, an AssertionError
would be raised.
To analyze the execution of .set_index()
method, .call_count
is used to display the number of times .set_index()
is called. Moreover, .call_args()
is used to display the arguments given to the .set_index()
method.