Reputation: 6418
I don't make a habit of this, but sometimes, in an effort to work around a circular import, I'll import a function from inside another function or method like this:
class MyClass:
def my_method(self):
from somewhere import the_thing
x = the_thing()
return x + 4
This works just fine, but I can't figure out how to test it. My usual fails with complaints that module "xyz" has no attribute "the_thing"
:
from unittest import TestCase
from unittest.mock import patch
class MyTestCase(TestCase):
@patch("path.to.my.module.the_thing")
def test_stuff(self):
...
Is there a way to mock functions imported at runtime? Is there a Better Way to do this?
Upvotes: 1
Views: 2320
Reputation: 2548
I have created following files in my system.
|-module
| |- __init__.py
| |- my_class.py
| |- xyz.py
|- test_my_class.py
module
is a folder with inside the file my_class.py
and the module xyz.py
besides that the empty file __init__.py
.
The production code inside the package module
is the following.
File xyz.py
:
def the_thing():
return 6
File my_class.py
:
class MyClass:
def my_method(self):
from module.xyz import the_thing
x = the_thing()
return x + 4
The content of the file test_my_class.py
is:
import unittest
from unittest.mock import patch
from module.my_class import MyClass
class MyTestCase(unittest.TestCase):
@patch("module.xyz.the_thing")
def test_stuff(self, mock_thing):
mock_thing.return_value = 20
self.assertEqual(24, MyClass().my_method())
def test_stuff_2(self):
self.assertEqual(10, MyClass().my_method())
if __name__ == '__main__':
unittest.main()
As you can see the test file defines 2 tests and only in the first test (test_stuff()
) is used the patch() function:
patch()
is defined the Mock object mock_thing
, which is passed to the test method as argument;test_stuff()
is defined the return_value
of the Mock object mock_thing
which substitute the production function the_thing()
The second test method (test_stuff_2()
) calls the simple production code of my_method()
and verifies its normal return value.
Upvotes: 3