Mocking a Python class static variable with Pytest

Viewed 1233

I am trying to properly create mocks for a class that has a dependency on a system library. Currently the code makes a connection to a socket for the library when being tested, and I am trying to remove that dependency.

class A:
    SETTING_VARIABLE = "CONFIG_VALUE"

    def __init__(self):
        self.system_connector = library.open(self.SETTING_VARIABLE)


import A

class B:
    INSTANCE_OF_A = A()

When class A is instantiated, it uses SETTING_VARIABLE to connect to a system library, which it can not do during a unit test, and my test suite fails during test collection. The library connector I am using can be configured to run in unit test mode, but requires a different configuration to be passed, so in this case SETTING_VARIABLE would need to be instantiated to "TEST_VALUE".

My test class test_B is failing as soon as B is imported when it tries to make a connection to the system library (I have disabled access to the socket for it). How can I set up Python mocking so that I can replace the value of the static variable defined by A?

One thing that I have tried to do from test_B:

import A
A.SETTING_VARIABLE = "TEST_VALUE"

This does seem to work, however is there a cleaner way to do this for unit tests?

1 Answers

Old but gold. Here is how this problem can be solved. The B class needs to be changed to initialize INSTANCE_OF_A in its constructor. Then you can mock the SETTING_VARIABLE using patch.object.

Complete example with patch.object as instruction or decorator:

A.py:

class A:
    SETTING_VARIABLE = "CONFIG_VALUE"

    def __init__(self):
        self.system_connector = library.open(self.SETTING_VARIABLE)

B.py:

from A import A

class B:
    def __init__(self):
        self.INSTANCE_OF_A = A()

test_B.py

import unittest
from unittest.mock import patch

from A import A
from B import B

class BTestCase(unittest.TestCase):

    @patch.object(A, "SETTING_VARIABLE", "TEST_VALUE")
    def test_b_with_decorator(self):
        INSTANCE_OF_B = B()

    def test_b_with_instruction(self):
        with patch.object(A, "SETTING_VARIABLE", "TEST_VALUE"):
            INSTANCE_OF_B = B()
Related