是否可以使用python模拟模块unittest.mock?我有一个名为的模块config,在运行测试时我想用另一个模块来模拟它test_config.我怎样才能做到这一点 ?谢谢.
config.py:
CONF_VAR1 = "VAR1"
CONF_VAR2 = "VAR2"
Run Code Online (Sandbox Code Playgroud)
test_config.py:
CONF_VAR1 = "test_VAR1"
CONF_VAR2 = "test_VAR2"
Run Code Online (Sandbox Code Playgroud)
所有其他模块从模块读取配置变量config.在运行测试时,我希望他们从test_config模块中读取配置变量.
如果你总是访问config.py中的变量,如下所示:
import config
...
config.VAR1
Run Code Online (Sandbox Code Playgroud)
您可以替换config您实际尝试测试的模块导入的模块.因此,如果您正在测试一个名为的模块foo,并且它导入并使用config,您可以说:
from mock import patch
import foo
import config_test
....
with patch('foo.config', new=config_test):
foo.whatever()
Run Code Online (Sandbox Code Playgroud)
但这实际上并没有全局替换模块,它只是在foo模块的命名空间中替换它.因此,您需要在导入的任何位置对其进行修补.如果foo这样做而不是import config:
from config import VAR1
Run Code Online (Sandbox Code Playgroud)
你也可以搞乱sys.modules这样做:
import config_test
import sys
sys.modules["config"] = config_test
# import modules that uses "import config" here, and they'll actually get config_test
Run Code Online (Sandbox Code Playgroud)
但一般来说,捣乱并不是一个好主意sys.modules,我不认为这种情况有任何不同.我赞成所有其他建议.
如果您想模拟整个模块,只需模拟使用该模块的导入即可。
myfile.py
import urllib
Run Code Online (Sandbox Code Playgroud)
test_myfile.py
import mock
import unittest
class MyTest(unittest.TestCase):
@mock.patch('myfile.urllib')
def test_thing(self, urllib):
urllib.whatever.return_value = 4
Run Code Online (Sandbox Code Playgroud)
foo.py:
import config
VAR1 = config.CONF_VAR1
def bar():
return VAR1
Run Code Online (Sandbox Code Playgroud)
test.py:
import unittest
import unittest.mock as mock
import test_config
class Test(unittest.TestCase):
def test_one(self):
with mock.patch.dict('sys.modules', config=test_config):
import foo
self.assertEqual(foo.bar(), 'test_VAR1')
Run Code Online (Sandbox Code Playgroud)
如您所见,该补丁甚至适用于执行期间执行的代码import foo.
考虑以下设置
配置.py:
import os
class Config(object):
CONF_VAR1 = "VAR1"
CONF_VAR2 = "VAR2"
class TestConfig(object):
CONF_VAR1 = "test_VAR1"
CONF_VAR2 = "test_VAR2"
if os.getenv("TEST"):
config = TestConfig
else:
config = Config
Run Code Online (Sandbox Code Playgroud)
现在您可以在代码中的其他任何地方使用:
from configuration import config
print config.CONF_VAR1, config.CONF_VAR2
Run Code Online (Sandbox Code Playgroud)
当你想模拟你的配置文件时,只需设置环境变量“TEST”。
额外加分:如果您有许多在测试和非测试代码之间共享的配置变量,那么您可以从 Config 派生 TestConfig 并简单地覆盖需要更改的变量:
class Config(object):
CONF_VAR1 = "VAR1"
CONF_VAR2 = "VAR2"
CONF_VAR3 = "VAR3"
class TestConfig(Config):
CONF_VAR2 = "test_VAR2"
# CONF_VAR1, CONF_VAR3 remain unchanged
Run Code Online (Sandbox Code Playgroud)