This content originally appeared on Level Up Coding - Medium and was authored by Rafi Muhammad Daffa
In a software development lifecycle, testing has become one of the most important activities to ensure that the software that we create fulfills the requirements and expectations of its users. Testing plays a vital role in identifying potential problems before the software is released for public use. Therefore, it is important a software’s test suite be sufficiently reliable and effective.
While manual testing methods also exist, some tests are automated using libraries which significantly decrease the time needed for each testing and increase the reliability of said tests. However, automated testing libraries usually consists of a rigid set of instructions which poses some problems, such as:
- Programs dependent on randomization or external factors may render any such tests unrepeatable in changing conditions.
- Programs dependent on other programs may break a test suite just because the other programs change.
These scenarios seem to negate the benefits of creating an automated testing suite. Since the test suite can easily produce unrepeatable results or even break altogether, it cannot be sufficiently relied upon, especially for large projects. However, we do need to remember that one of the best practice programming principle is dependency inversion (a program should not/should reduce dependency towards concrete implementations).
To solve the dependency problem, a program must be planned in such a way that it depends on an abstraction, rather than a concrete implementation. In languages such as Java and Kotlin, this is easily achievable using interfaces whose implementation can be swapped during tests. However, Python does not know about interfaces. Therefore, Python’s built-in testing library provides a set of methods to create and use mock objects in tests.
Creating Mock Objects
Mock objects are useful to reduce dependency of the program under test towards other classes/objects. Mock objects can stand in the position of all objects (since Python does not enforce static type checking anyways) and can mimic the behaviors of any objects. Attributes can be added at will and object methods can also be configured with specific return values, all without defining or using the actual object itself. These feats can be achieved through the Mock class under the unittest.mock module in Python.
from unittest.mock import Mock
mock_object = Mock()
It is important to note that a mock object is not required to mock all aspects of a particular object to be able to be used in that object’s position. We can mock only the aspects that are needed to test our program.
Let’s take a HttpRequest object in Django as an example. The following method is a view function to create a relationship between a user and a project that he/she is working on:
In this case, the required input is only the user’s ID and account type (which is included in the request payload) and also the project’s ID (which is included in the request body through the registration_data parameter). Since the user’s ID and account type is obtained from the HttpRequest object that is passed to this function, any tests for this function must either supply this object or find a way to mock it.
FYI, a HttpRequest object is a complex object which includes attributes such as client user agent, IP address, and others. We don’t need such attributes when testing this function. We only need the object to have the appropriate user ID field, which is embedded inside the request.auth field. Therefore, we can use mock objects in the request object’s position by making just that particular field to be available. The result is shown below:
request_mock = mock.Mock()
request_mock.auth = mock.Mock()
request_mock.auth.id = self.annotator_user.id
request_mock.auth.account_type = User.ANNOTATOR
In the above mock object, we are creating a mock request object called request_mock. Inside the object, we inject the auth field using another mock object, which is later also injected by the test user’s ID and account type. Since this is the only information that the function will need, we won’t need to mock any other fields and simply pass along the object as the function’s argument. We now can execute the test as though an actual request object is passed.
This technique can be applied to any objects, provided that you know exactly what part of the program will be used. In Java and Kotlin, these can be easily specified through interfaces. However, in Python, the developer’s consciousness to plan ahead regarding the object’s usage is important.
Increasing Test Reliability in Python through Object Mocking was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Level Up Coding - Medium and was authored by Rafi Muhammad Daffa

Rafi Muhammad Daffa | Sciencx (2021-05-07T22:12:51+00:00) Increasing Test Reliability in Python through Object Mocking. Retrieved from https://www.scien.cx/2021/05/07/increasing-test-reliability-in-python-through-object-mocking/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.