是否可以使用unittest.mock
在python中模拟模块?我有一个名为config
的模块,在运行测试时我想用另一个模块test_config
来模拟它。我怎样才能做到这一点 ?感谢。
config.py:
CONF_VAR1 = "VAR1"
CONF_VAR2 = "VAR2"
test_config.py:
CONF_VAR1 = "test_VAR1"
CONF_VAR2 = "test_VAR2"
所有其他模块从config
模块读取配置变量。在运行测试时,我希望他们从test_config
模块中读取配置变量。
答案 0 :(得分:7)
如果您一直在访问config.py中的变量,请执行以下操作:
import config
...
config.VAR1
您可以替换您实际尝试测试的模块导入的config
模块。因此,如果您正在测试名为foo
的模块,并导入并使用config
,则可以说:
from mock import patch
import foo
import config_test
....
with patch('foo.config', new=config_test):
foo.whatever()
但实际上并没有全局替换模块,它只是在foo
模块的命名空间中替换它。因此,您需要在导入的任何位置对其进行修补。如果foo
执行此操作而不是import config
:
from config import VAR1
您还可以使用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
但一般来说,混淆sys.modules
不是一个好主意,我不认为这种情况有任何不同。我赞成所有其他建议。
答案 1 :(得分:5)
<强> foo.py:强>
import config
VAR1 = config.CONF_VAR1
def bar():
return VAR1
<强> 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')
如您所见,该补丁甚至适用于import foo
期间执行的代码。
答案 2 :(得分:1)
如果您的申请(&#34; app.py&#34;说)看起来像
import config
print config.var1, config.var2
并提供输出:
$ python app.py
VAR1 VAR2
您可以使用mock.patch
修补各个配置变量:
from mock import patch
with patch('config.var1', 'test_VAR1'):
import app
这导致:
$ python mockimport.py
test_VAR1 VAR2
虽然我不确定这是否可以在模块级别进行。
答案 3 :(得分:1)
如果您想模拟整个模块,只需模拟使用该模块的导入即可。
for (i = 0; i < $("li").length; i++) {
// Get the initial text of every list item
let initialText = $("li").eq(i).attr("class");
// Remove the whitespace and convert to lower case
let newText = initialText.replace(/ /g, "").toLowerCase();
// Set the list item class to the new text
$("li").eq(i).attr("class", newText);
}
myfile.py
import urllib
test_myfile.py
答案 4 :(得分:0)
考虑以下设置
configuration.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
现在您可以使用代码中的其他地方:
from configuration import config
print config.CONF_VAR1, config.CONF_VAR2
当你想模拟你的配置文件时,只需设置环境变量“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