【发布时间】:2018-05-24 09:55:13
【问题描述】:
我正在编写一个 CLI 以使用 elasticsearch-py 库与 elasticsearch 交互。我正在尝试模拟 elasticsearch-py 函数,以便在不调用我的真实集群的情况下测试我的函数。
我读了this question 和this one,但我还是不明白。
main.py
Escli继承自cliff的Appclass
class Escli(App):
_es = elasticsearch5.Elasticsearch()
settings.py
from escli.main import Escli
class Settings:
def get(self, sections):
raise NotImplementedError()
class ClusterSettings(Settings):
def get(self, setting, persistency='transient'):
settings = Escli._es.cluster\
.get_settings(include_defaults=True, flat_settings=True)\
.get(persistency)\
.get(setting)
return settings
settings_test.py
import escli.settings
class TestClusterSettings(TestCase):
def setUp(self):
self.patcher = patch('elasticsearch5.Elasticsearch')
self.MockClass = self.patcher.start()
def test_get(self):
# Note this is an empty dict to show my point
# it will contain childs dict to allow my .get(persistency).get(setting)
self.MockClass.return_value.cluster.get_settings.return_value = {}
cluster_settings = escli.settings.ClusterSettings()
ret = cluster_settings.get('cluster.routing.allocation.node_concurrent_recoveries', persistency='transient')
# ret should contain a subset of my dict defined above
我想让Escli._es.cluster.get_settings() 返回我想要的内容(dict 对象),以便不进行真正的 HTTP 调用,但它一直在这样做。
我所知道的:
为了模拟实例方法,我必须执行类似的操作
MagicMockObject.return_value.InstanceMethodName.return_value = ...我无法修补
Escli._es.cluster.get_settings,因为 Python 尝试将Escli作为模块导入,但无法正常工作。所以我正在修补整个库。
我拼命想在任何地方放一些return_value,但我不明白为什么我不能正确地模拟那个东西。
【问题讨论】:
-
你必须模拟你在哪里测试。由于您正在测试
settings.py模块,因此您需要相应地引用您的模拟。因此,在您的setUp中,您的patch路径应该类似于:patch('escli.settings.Escli')。因此,现在当您像在测试中一样显式调用settings代码时,您现在可以在正确的位置正确地模拟了。 -
此外,您可能希望使用 Elasticsearch 类指定您的
Mock,以验证您正在使用该类中可用的有效属性。因此,您可能需要执行以下操作:patch('escli.settings.Escli', Mock(Elasticsearch)) -
只是把它放在那里,
pytest确实提供了一个插件,如果您也对其他选项感兴趣,您可以将其用于弹性搜索:pypi.org/project/pytest-elasticsearch -
你成就了我的一天!我会深入了解
Mock()的事情。您会考虑在解决此案时做出回答吗? -
很高兴它有帮助!我发布了答案。干杯。
标签: python unit-testing elasticsearch mocking