python:模拟一个模块

Ris*_*edi 11 python mocking

是否可以使用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模块中读取配置变量.

dan*_*ano 9

如果你总是访问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,我不认为这种情况有任何不同.我赞成所有其他建议.


kag*_*ick 7

如果您想模拟整个模块,只需模拟使用该模块的导入即可。

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)


and*_*and 6

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.

  • @naxa,您可以将字典传递给此函数`patch.dict('sys.modules', {'config.foo': test_config})` ([docs](https://docs.python.org/3/图书馆/unittest.mock.html#unittest.mock.patch.dict)) (2认同)

gil*_*sho 1

考虑以下设置

配置.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)