How to mock a constant value

130 Views Asked by At

I have a structure like so:

mod1
├── mod2
│   ├── __init__.py
│   └── utils.py
└── tests
    └── test_utils.py

where

  • __init__.py:
CONST = -1
  • utils.py:
from mod1.mod2 import CONST

def mod_function():
    print(CONST)
  • test_utils.py:
from mod1.mod2.utils import mod_function

def test_mod_function(mocker):
    mock = mocker.patch("mod1.mod2.CONST")
    mock.return_value = 1000
    mod_function()

I'm using pytest with mocker.

By running python -m pytest -s ./mod1/tests I expected to see 1000 as an output, but got -1. Why?

How to patch a constant from the __init__.py file?

1

There are 1 best solutions below

0
On BEST ANSWER

What patch("mod1.mod2.CONST") does is really to set the CONST attribute of the module object mod1.mod2 to a different object. It does not affect any existing names referencing the original mod1.mod2.CONST object.

When utils.py does:

from mod1.mod2 import CONST

it creates a name CONST in the namespace of the mod1.mod2.utils module, referencing the object -1 currently referenced by the mod1.mod2.CONST name.

And when test_mod_function then does:

mock = mocker.patch("mod1.mod2.CONST")

it modifies mod1.mod2 such that its CONST attribute now references a Mock object, while the CONST name in mod1.mod2.utils continues to reference the object -1, which is why setting mock.return_value does not affect the outcome of mod_function.

To properly test mod_function with a mock CONST you can either patch CONST in the namespace where mod_function is defined:

mock = mocker.patch("mod1.mod2.utils.CONST")

or you can defer the import of mod1.mod2.utils until mod1.mod2.CONST has been patched:

def test_mod_function(mocker):
    mock = mocker.patch("mod1.mod2.CONST")
    mock.return_value = 1000
    from mod1.mod2.utils import mod_function
    mod_function()