如何在 python 单元测试中模拟未在本地安装的库?
How to mock in a python unittest a library not installed locally?
我正在尝试使用 unittest
以 (my_app.py
):
开头的 python 3.6 脚本进行测试
import sys
from awsglue.utils import getResolvedOptions
args = getResolvedOptions(sys.argv, ['opt1', 'opt2', 'opt3'])
opt1 = args['opt1']
opt2 = args['opt2']
opt3 = args['opt3']
....
所以在我的测试中我做了类似的事情:
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 = {}
....
但测试很快在 import my_app
失败,原因是:
ModuleNotFoundError: No module named 'awsglue'
因为没有 awsglue
本地安装。我如何测试导入非本地安装的库并在我的测试中模拟它的模块?
您需要在导入 my_app
之前模拟导入的模块。 patch
在这里不起作用,因为 patch
导入模块是为了修补它。在这种情况下,导入本身会导致错误。
要做到这一点,最简单的方法是让 python 认为 awsglue
已经被导入。您可以通过将模拟直接放在 sys.modules
字典中来做到这一点。在此之后,您可以执行 my_app
导入。
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
您可以将导入 hack 部分移动到 setup
fixture 方法。
但是我建议只安装软件包。导入 hack 可能很难维护。
我正在尝试使用 unittest
以 (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']
....
所以在我的测试中我做了类似的事情:
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 = {}
....
但测试很快在 import my_app
失败,原因是:
ModuleNotFoundError: No module named 'awsglue'
因为没有 awsglue
本地安装。我如何测试导入非本地安装的库并在我的测试中模拟它的模块?
您需要在导入 my_app
之前模拟导入的模块。 patch
在这里不起作用,因为 patch
导入模块是为了修补它。在这种情况下,导入本身会导致错误。
要做到这一点,最简单的方法是让 python 认为 awsglue
已经被导入。您可以通过将模拟直接放在 sys.modules
字典中来做到这一点。在此之后,您可以执行 my_app
导入。
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
您可以将导入 hack 部分移动到 setup
fixture 方法。
但是我建议只安装软件包。导入 hack 可能很难维护。