在模块中导入之前模拟库

Nil*_*esh 5 python unit-testing mocking python-mock

我有 python 文件

\n\n
$ tree .\n.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 app\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 my_module.py\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 setup.py\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 test_my_module.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 tox.ini\n\n1 directory, 5 files\n
Run Code Online (Sandbox Code Playgroud)\n\n

my_module.py

\n\n
$ cat app/my_module.py\nfrom pymongo import MongoClient\n\nclient = MongoClient(\'mongodb://localhost:27017/\')\n\npost = client.test_database.posts.find_one()\n\ndef ret_value():\n    return db.posts\n
Run Code Online (Sandbox Code Playgroud)\n\n

毒物文件

\n\n
$ cat tox.ini\n[tox]\nenvlist = py35\n\n[testenv]\ndeps=\n    coverage>=4.1\n    flake8\n    pylint\n    pytest-cov==2.2.1\n    pytest==3.0.7\n    pytest-mock\n    pytest-xdist\n        pymongo\n        mock\ncommands=py.test -n 5 -l\nsetenv =\n    XYZ = 123\n
Run Code Online (Sandbox Code Playgroud)\n\n

测试我的模块.py

\n\n
$ cat test_my_module.py\nimport os\n\nimport mock\n\nwith mock.patch(\'app.my_module.MongoClient\'):\n    from app import my_module\n\ndef test_my_module_method():\n    assert os.getenv(\'XYZ\') == \'123\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

在 中my_module.py,它在导入时创建 mongodb 连接。我想在导入之前嘲笑它my_module测试用例之前模拟它。

\n\n

它给出了错误

\n\n
$ tox -v\nusing tox.ini: /private/tmp/testing/tox.ini\nusing tox-2.9.1 from /Library/Python/2.7/site-packages/tox/__init__.pyc\nGLOB sdist-make: /private/tmp/testing/setup.py\n  /private/tmp/testing$ /usr/bin/python /private/tmp/testing/setup.py sdist --formats=zip --dist-dir /private/tmp/testing/.tox/dist >/private/tmp/testing/.tox/log/tox-0.log\npy35 reusing: /private/tmp/testing/.tox/py35\npy35 inst-nodeps: /private/tmp/testing/.tox/dist/Tox Testing-0.0.0.zip\n  /private/tmp/testing$ /private/tmp/testing/.tox/py35/bin/pip install -U --no-deps /private/tmp/testing/.tox/dist/Tox Testing-0.0.0.zip >/private/tmp/testing/.tox/py35/log/py35-4.log\n  /private/tmp/testing$ /private/tmp/testing/.tox/py35/bin/pip freeze >/private/tmp/testing/.tox/py35/log/py35-5.log\npy35 installed: apipkg==1.4,astroid==1.5.3,coverage==4.4.2,execnet==1.5.0,flake8==3.5.0,isort==4.2.15,lazy-object-proxy==1.3.1,mccabe==0.6.1,mock==2.0.0,pbr==3.1.1,py==1.5.2,pycodestyle==2.3.1,pyflakes==1.6.0,pylint==1.7.4,pymongo==3.5.1,pytest==3.0.7,pytest-cov==2.2.1,pytest-forked==0.2,pytest-mock==1.6.3,pytest-xdist==1.20.1,six==1.11.0,Tox-Testing==0.0.0,wrapt==1.10.11\npy35 runtests: PYTHONHASHSEED=\'2635490598\'\npy35 runtests: commands[0] | py.test -n 5 -l\n  /private/tmp/testing$ /private/tmp/testing/.tox/py35/bin/py.test -n 5 -l\n=============================================================================== test session starts ===============================================================================\nplatform darwin -- Python 3.5.2, pytest-3.0.7, py-1.5.2, pluggy-0.4.0\nrootdir: /private/tmp/testing, inifile:\nplugins: xdist-1.20.1, mock-1.6.3, forked-0.2, cov-2.2.1\ngw0 [0] / gw1 [0] / gw2 [0] / gw3 [0] / gw4 [0]\nscheduling tests via LoadScheduling\n\n===================================================================================== ERRORS ======================================================================================\n_______________________________________________________________________ ERROR collecting test_my_module.py ________________________________________________________________________\ntest_my_module.py:5: in <module>\n    with mock.patch(\'app.my_module.MongoClient\'):\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1353: in __enter__\n    self.target = self.getter()\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1523: in <lambda>\n    getter = lambda: _importer(target)\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1210: in _importer\n    thing = _dot_lookup(thing, comp, import_path)\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1199: in _dot_lookup\n    __import__(import_path)\napp/my_module.py:5: in <module>\n    post = client.test_database.posts.find_one()\n.tox/py35/lib/python3.5/site-packages/pymongo/collection.py:1109: in find_one\n    for result in cursor.limit(-1):\n.tox/py35/lib/python3.5/site-packages/pymongo/cursor.py:1132: in next\n    if len(self.__data) or self._refresh():\n.tox/py35/lib/python3.5/site-packages/pymongo/cursor.py:1055: in _refresh\n    self.__collation))\n.tox/py35/lib/python3.5/site-packages/pymongo/cursor.py:892: in __send_message\n    **kwargs)\n.tox/py35/lib/python3.5/site-packages/pymongo/mongo_client.py:933: in _send_message_with_response\n    server = topology.select_server(selector)\n.tox/py35/lib/python3.5/site-packages/pymongo/topology.py:214: in select_server\n    address))\n.tox/py35/lib/python3.5/site-packages/pymongo/topology.py:189: in select_servers\n    self._error_message(selector))\nE   pymongo.errors.ServerSelectionTimeoutError: localhost:27017: [Errno 61] Connection refused\n_______________________________________________________________________ ERROR collecting test_my_module.py ________________________________________________________________________\ntest_my_module.py:5: in <module>\n    with mock.patch(\'app.my_module.MongoClient\'):\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1353: in __enter__\n    self.target = self.getter()\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1523: in <lambda>\n    getter = lambda: _importer(target)\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1210: in _importer\n    thing = _dot_lookup(thing, comp, import_path)\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1199: in _dot_lookup\n    __import__(import_path)\napp/my_module.py:5: in <module>\n    post = client.test_database.posts.find_one()\n.tox/py35/lib/python3.5/site-packages/pymongo/collection.py:1109: in find_one\n    for result in cursor.limit(-1):\n.tox/py35/lib/python3.5/site-packages/pymongo/cursor.py:1132: in next\n    if len(self.__data) or self._refresh():\n.tox/py35/lib/python3.5/site-packages/pymongo/cursor.py:1055: in _refresh\n    self.__collation))\n.tox/py35/lib/python3.5/site-packages/pymongo/cursor.py:892: in __send_message\n    **kwargs)\n.tox/py35/lib/python3.5/site-packages/pymongo/mongo_client.py:933: in _send_message_with_response\n    server = topology.select_server(selector)\n.tox/py35/lib/python3.5/site-packages/pymongo/topology.py:214: in select_server\n    address))\n.tox/py35/lib/python3.5/site-packages/pymongo/topology.py:189: in select_servers\n    self._error_message(selector))\nE   pymongo.errors.ServerSelectionTimeoutError: localhost:27017: [Errno 61] Connection refused\n_______________________________________________________________________ ERROR collecting test_my_module.py ________________________________________________________________________\ntest_my_module.py:5: in <module>\n    with mock.patch(\'app.my_module.MongoClient\'):\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1353: in __enter__\n    self.target = self.getter()\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1523: in <lambda>\n    getter = lambda: _importer(target)\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1210: in _importer\n    thing = _dot_lookup(thing, comp, import_path)\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1199: in _dot_lookup\n    __import__(import_path)\napp/my_module.py:5: in <module>\n    post = client.test_database.posts.find_one()\n.tox/py35/lib/python3.5/site-packages/pymongo/collection.py:1109: in find_one\n    for result in cursor.limit(-1):\n.tox/py35/lib/python3.5/site-packages/pymongo/cursor.py:1132: in next\n    if len(self.__data) or self._refresh():\n.tox/py35/lib/python3.5/site-packages/pymongo/cursor.py:1055: in _refresh\n    self.__collation))\n.tox/py35/lib/python3.5/site-packages/pymongo/cursor.py:892: in __send_message\n    **kwargs)\n.tox/py35/lib/python3.5/site-packages/pymongo/mongo_client.py:933: in _send_message_with_response\n    server = topology.select_server(selector)\n.tox/py35/lib/python3.5/site-packages/pymongo/topology.py:214: in select_server\n    address))\n.tox/py35/lib/python3.5/site-packages/pymongo/topology.py:189: in select_servers\n    self._error_message(selector))\nE   pymongo.errors.ServerSelectionTimeoutError: localhost:27017: [Errno 61] Connection refused\n_______________________________________________________________________ ERROR collecting test_my_module.py ________________________________________________________________________\ntest_my_module.py:5: in <module>\n    with mock.patch(\'app.my_module.MongoClient\'):\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1353: in __enter__\n    self.target = self.getter()\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1523: in <lambda>\n    getter = lambda: _importer(target)\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1210: in _importer\n    thing = _dot_lookup(thing, comp, import_path)\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1199: in _dot_lookup\n    __import__(import_path)\napp/my_module.py:5: in <module>\n    post = client.test_database.posts.find_one()\n.tox/py35/lib/python3.5/site-packages/pymongo/collection.py:1109: in find_one\n    for result in cursor.limit(-1):\n.tox/py35/lib/python3.5/site-packages/pymongo/cursor.py:1132: in next\n    if len(self.__data) or self._refresh():\n.tox/py35/lib/python3.5/site-packages/pymongo/cursor.py:1055: in _refresh\n    self.__collation))\n.tox/py35/lib/python3.5/site-packages/pymongo/cursor.py:892: in __send_message\n    **kwargs)\n.tox/py35/lib/python3.5/site-packages/pymongo/mongo_client.py:933: in _send_message_with_response\n    server = topology.select_server(selector)\n.tox/py35/lib/python3.5/site-packages/pymongo/topology.py:214: in select_server\n    address))\n.tox/py35/lib/python3.5/site-packages/pymongo/topology.py:189: in select_servers\n    self._error_message(selector))\nE   pymongo.errors.ServerSelectionTimeoutError: localhost:27017: [Errno 61] Connection refused\n_______________________________________________________________________ ERROR collecting test_my_module.py ________________________________________________________________________\ntest_my_module.py:5: in <module>\n    with mock.patch(\'app.my_module.MongoClient\'):\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1353: in __enter__\n    self.target = self.getter()\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1523: in <lambda>\n    getter = lambda: _importer(target)\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1210: in _importer\n    thing = _dot_lookup(thing, comp, import_path)\n.tox/py35/lib/python3.5/site-packages/mock/mock.py:1199: in _dot_lookup\n    __import__(import_path)\napp/my_module.py:5: in <module>\n    post = client.test_database.posts.find_one()\n.tox/py35/lib/python3.5/site-packages/pymongo/collection.py:1109: in find_one\n    for result in cursor.limit(-1):\n.tox/py35/lib/python3.5/site-packages/pymongo/cursor.py:1132: in next\n    if len(self.__data) or self._refresh():\n.tox/py35/lib/python3.5/site-packages/pymongo/cursor.py:1055: in _refresh\n    self.__collation))\n.tox/py35/lib/python3.5/site-packages/pymongo/cursor.py:892: in __send_message\n    **kwargs)\n.tox/py35/lib/python3.5/site-packages/pymongo/mongo_client.py:933: in _send_message_with_response\n    server = topology.select_server(selector)\n.tox/py35/lib/python3.5/site-packages/pymongo/topology.py:214: in select_server\n    address))\n.tox/py35/lib/python3.5/site-packages/pymongo/topology.py:189: in select_servers\n    self._error_message(selector))\nE   pymongo.errors.ServerSelectionTimeoutError: localhost:27017: [Errno 61] Connection refused\n============================================================================= pytest-warning summary ==============================================================================\nWC1 None pytest_funcarg__cov: declaring fixtures using "pytest_funcarg__" prefix is deprecated and scheduled to be removed in pytest 4.0.  Please remove the prefix and use the @pytest.fixture decorator instead.\nWC1 None pytest_funcarg__cov: declaring fixtures using "pytest_funcarg__" prefix is deprecated and scheduled to be removed in pytest 4.0.  Please remove the prefix and use the @pytest.fixture decorator instead.\nWC1 None pytest_funcarg__cov: declaring fixtures using "pytest_funcarg__" prefix is deprecated and scheduled to be removed in pytest 4.0.  Please remove the prefix and use the @pytest.fixture decorator instead.\nWC1 None pytest_funcarg__cov: declaring fixtures using "pytest_funcarg__" prefix is deprecated and scheduled to be removed in pytest 4.0.  Please remove the prefix and use the @pytest.fixture decorator instead.\nWC1 None pytest_funcarg__cov: declaring fixtures using "pytest_funcarg__" prefix is deprecated and scheduled to be removed in pytest 4.0.  Please remove the prefix and use the @pytest.fixture decorator instead.\nWC1 None pytest_funcarg__cov: declaring fixtures using "pytest_funcarg__" prefix is deprecated and scheduled to be removed in pytest 4.0.  Please remove the prefix and use the @pytest.fixture decorator instead.\n=================================================================== 6 pytest-warnings, 5 error in 34.93 seconds ===================================================================\nERROR: InvocationError: \'/private/tmp/testing/.tox/py35/bin/py.test -n 5 -l\'\n_____________________________________________________________________________________ summary _____________________________________________________________________________________\nERROR:   py35: commands failed\n
Run Code Online (Sandbox Code Playgroud)\n\n

有什么方法可以在导入之前模拟它吗?

\n