Patch function with the same name as its module

Author: Swen Kooij

Date: 2021-11-25

Imagine we have following Python module:

mymodule/
    somefunc.py
    __init__.py


# somefunc.py
def somefunc():
    pass


# __init__.py
from .somefunc import somefunc

The most obvious way to patch this would be:

from unittest.mock import patch

with patch("mymodule.somefunc.somefunc"):
    ...

We”d immediately get an error:

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    with patch("mymodule.somefunc.somefunc") as mock:
  File "/Users/swen/.pyenv/versions/3.8.5/lib/python3.8/unittest/mock.py", line 1393, in __enter__
    original, local = self.get_original()
  File "/Users/swen/.pyenv/versions/3.8.5/lib/python3.8/unittest/mock.py", line 1366, in get_original
    raise AttributeError(
AttributeError: <function somefunc at 0x107a969d0> does not have the attribute "somefunc"

The next obvious step is to try to leave off the module name:

from unittest.mock import patch

with patch("mymodule.somefunc"):
    ...

This doesn”t raise an error, but it doesnt” actually patch the function. It ends up patching the somefunc module instead. The only way to work around this is to use unittest.mock.patch.object:

import sys

from unittest.mock import patch

with patch.object(sys.modules["mymodule.somefunc"], "somefunc"):
    ...

This correctly patches the function and not the module.