I am trying to test using unittest
a python 3.6 script that starts with (my_app.py
):
import sys
from awsglue.utils import getResolvedOptions
args = getResolvedOptions(sys.argv, ['opt1', 'opt2', 'opt3'])
opt1 = args['opt1']
opt2 = args['opt2']
opt3 = args['opt3']
....
so in my test I did something like:
import unittest
import datetime
from mock import patch
import my_app
class TestMyApp(unittest.TestCase):
@patch('awsglue.utils.getResolvedOptions')
def test_mock_stubs(self, patch_opts):
patch_opts.return_value = {}
....
but the test soon fails at import my_app
with:
ModuleNotFoundError: No module named 'awsglue'
as there is not awsglue
locally installed. How can I test a module that import a not locally installed library and also mock it in my test?
You'll need to mock the imported module before the import for my_app
happens. patch
won't work here, because patch
imports the module in order to patch it. And in this case, that import itself would cause an error.
To do this the simplest way is to trick python into thinking that awsglue
is already imported. You can do that by putting your mock directly in the sys.modules
dictionary. After this you can do the my_app
import.
import unittest
import sys
from unittest import mock
class TestMyApp(unittest.TestCase):
def test_mock_stubs(self):
# mock the module
mocked_awsglue = mock.MagicMock()
# mock the import by hacking sys.modules
sys.modules['awsglue.utils'] = mocked_awsglue
mocked_awsglue.getResolvedOptions.return_value = {}
# move the import here to make sure that the mocks are setup before it's imported
import my_app
You can move the import hack part to a setup
fixture method.
However I would suggest just installing the package. The import hack can be very difficult to maintain.