【发布时间】:2021-08-27 07:12:46
【问题描述】:
我正在尝试仅在类的特定实例上模拟属性。为了简化示例,我有一个Thing,它使用name 进行初始化,并且基于此名称,该类将在预定义的位置/conf/{name}_conf.yaml 中加载配置文件。
在测试时,会创建几个 Thing 实例,我只想覆盖其中一个的配置。
我在下面评论了我必须更改才能使其工作的初始代码:
class Thing():
def __init__(self, name):
self.name = name
# I wasn't able to mock this:
# self.configuration_name = f'/configuration/{self.name}_configuration.yaml'
# @property <- nor this
def configuration_filename(self):
return f'/configuration/{self.name}_configuration.yaml'
在我的测试中,模拟应该能够将不同的配置文件(特定于测试)作为参数,但只能应用于名为 test_thing 的 Thing 实例。
我得到了它与上面的实现这样的工作:
configuration_filename_orig = Thing.configuration_filename
def my_patched_configuration_filename(self, configuration_filename, *args, **kwargs):
if self.slug == 'cmstest':
return configuration_filename
else:
return configuration_filename_orig(self, *args, **kwargs)
然后我可以像这样为每个测试类“注入”一个自定义测试配置文件:
from functools import partial
from test.utils import my_patched_configuration_filename
...
@patch.object(Thing, 'configuration_filename', autospec=True, side_effect=partial(my_patched_configuration_filename, configuration_filename='testdata/test_1.yaml'))
class ConfigurationTests(TestCase):
def test_1(self, mocked_conf):
# test something
def test_2(self, mocked_conf):
# test something else
@patch.object(Thing, 'configuration_filename', autospec=True, side_effect=partial(my_patched_configuration_filename, configuration_filename='testdata/test_2.yaml'))
class ConfigurationTestsAdvanced(TestCase):
def test_1(self, mocked_conf):
# test something
def test_2(self, mocked_conf):
# test something else
现在...这可行,但我想知道是否有办法做类似的事情,但在 Thing 类上具有真实属性(使用 @property 装饰器或在 __init__ 中初始化的属性方法)。
我花了几个小时尝试不同的东西......但主要问题似乎是使用 return_value 不会将 self 参数传递给模拟,所以我不能使用它。
有什么想法吗?
【问题讨论】:
-
您是否使用property mock 模拟该属性?
-
我试过了,但据我所知
PropertyMock接受return_value,我需要它根据实例起作用(需要selfarg)。如果我使用带有副作用的PropertyMock,我也不会得到self。如果PropertyMock有办法,我还没找到:(
标签: python unit-testing mocking