Mocking using pytest

Pytest is a unit test module in python.
Mocking is a way of mimicking the working of a service in
a way to substitute for the real one.

In this post I'll be focussing on mocking different types of methods present in a class.

Class ABC has been defined in a python file python_class.py

class ABC:

    def call(self):
        self.static_method()
        ABC.class_method()
        self.instance_method()
        self._ABC__private_instance_method()
        ABC._ABC__private_class_method()
        ABC._ABC__private_static_method()

    @staticmethod
    def static_method():
        print("static_method")

    @classmethod
    def class_method(cls):
        print("class_method")

    def instance_method(self):
        print("instance method")

    def __private_instance_method(self):
        print("private instance method")

    @classmethod
    def __private_class_method(cls):
        print("private class method")

    @staticmethod
    def __private_static_method():
        print("private static method")

Yeah I know this isn't how class methods and static methods should be used, but that's not on today's agenda.

In the call method, we can see that there are 6 other methods being called. That's where we need to mock the methods - the place where they're being called/being used instead of where they've been defined.

But before that we need to install 2 packages: pytest, pytest-mock

from unittest.mock import Mock
from python_class import ABC


class TestPythonClass():
    def test_all_methods(self, mocker):
        directory = "python_class.ABC"
        instance_mock = mocker.patch(f"{directory}.instance_method", return_value=Mock())
        static_mock = mocker.patch(f"{directory}.static_method", return_value=Mock())
        class_method_mock = mocker.patch(f"{directory}.class_method", return_value=Mock())
        pvt_instance_mock = mocker.patch(f"{directory}._ABC__private_instance_method", return_value=Mock())
        pvt_class_mock = mocker.patch(f"{directory}._ABC__private_class_method", return_value=Mock())
        pvt_static_mock = mocker.patch(f"{directory}._ABC__private_static_method", return_value=Mock())

        ABC().call()

        assert instance_mock.call_count == 1
        assert static_mock.call_count == 1
        assert class_method_mock.call_count == 1
        assert pvt_instance_mock.call_count == 1
        assert pvt_class_mock.call_count == 1

mocker is a fixture that is shipped with the pytest-mock module. We can simply pass it on as an argument during the test method definition without importing.

In this way I've mocked 6 different types of methods:

  • instance method
  • class method
  • static method
  • private instance method
  • private class method
  • private static method

Lemme know in case I missed something or I need to add anything.

19