My directory structure looks like this:
myproject/
├── mymodule/
│ ├── foo.py
│ └── model/
│ └── functions.py
│
└── tests/
└── footest.py
my foo.py
file has a local import that looks like this:
from .model.functions import MyClass
I am trying to mock one of the MyClass methods in one of my tests but I can't figure out how to use the @patch
decorator to do it. Normally I do this:
class CheckLambdaHandler(unittest.TestCase):
@patch('requests.post')
def test_post_error(self, mocked_post):
# Test which uses requests.post
But when I try to do something similar with a local import, it breaks:
class CheckLambdaHandler(unittest.TestCase):
@patch('.model.functions.MyClass.function')
def test_post_error(self, mocked_post):
# Test which uses requests.post
Because I guess @patch does a string split on "." which means you cant use local imports?
ValueError: Empty module name
Anyone else know what to do here? Do I need to change my import? In the test? In the actual code?
From the docs:
target should be a string in the form
'package.module.ClassName'
. The target is imported and the specified object replaced with the new object, so the target must be importable from the environment you are callingpatch()
from.
Since the test code does not usually reside within the package, the relative import does not make sense here.
Change your target "path" in the patch (test code) to use an absolute path. Your library code need not be changed. Assuming mymodule
is the top-level package name, and myproject
is the project root, that would look like:
@patch('mymodule.model.functions.MyClass.function')