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()
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?
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()