仅模拟类的所有实例的一个属性

问题描述 投票:0回答:1

我有这3个模块:

# config.py
class Config:
    def __init__(self):
        self.some_attribute = "some value"  # <-- I want to mock this attribute
        self.another_attribute = 123
# some_module.py
from config import Config

def method_that_uses_config():
    print(Config().another_attribute)  # This should not be mocked
    return Config().some_attribute  # This should be mocked
# test_some_module.py:
from unittest.mock import patch

from some_module import method_that_uses_config

class TestConfig:
    @patch("some_module.Config")
    def test_method_that_uses_config(self, mock_config):
        mock_config.return_value.some_attribute = "mocked value"
        assert method_that_uses_config() == "mocked value"

这仅部分有效。 Config 类现在已被完全模拟,而我只想模拟一个特定属性并保持其余属性不变:

Config().some_attribute
# 'mocked value'
Config().another_attribute
# <MagicMock name='Config().another_attribute' id='4329847393'>

我希望

Config().another_attribute
返回其原始值 (
123
)。 我基本上希望 Config 实例的行为与通常一样,唯一的例外是模拟属性。

我认为这应该是非常基本的,但我可能遗漏了一些东西。

python unit-testing mocking
1个回答
0
投票

这是基于更改为使用

Config
的一个共享实例,而不是重复调用
Config
来制作新副本。为了简单起见,我们只使用类
Config
本身作为该实例,而不是实例化它。

# config.py
class C:
    some_attribute = "some value"
    another_attribute = 123

# some_module.py
from config import Config

def method_that_uses_config():
    print(Config.another_attribute)
    return Config.some_attribute

对于您的测试,您可以使用

unittest.mock.patch.object
来替换您要更改的属性的值。

# test_some_module.py:
from unittest.mock import patch

from some_module import method_that_uses_config

class TestConfig:
    @patch.object(some_module.Config, 'some_attribute', "mocked value")
    def test_method_that_uses_config(self, mock_config):
        assert method_that_uses_config() == "mocked value"

这里快速演示了

patch.object
的工作原理。

>>> Config = class('Config', (), dict(a=1, b=2))
>>> p = patch.object(Config, 'a', 5)
>>> Config.a, Config.b
(1, 2)
>>> p.start()
5
>>> Config.a, Config.b
(5, 2)
>>> p.stop()
False
>>> Config.a, Config.b
(1, 2)

start
stop
方法基本上是
__enter__
__exit__
方法的包装,允许您使用相同的补丁手动“模拟”
with
语句。

© www.soinside.com 2019 - 2024. All rights reserved.