Jér*_*Pin 6 python unit-testing mocking elasticsearch
我正在编写一个CLI,使用elasticsearch-py库与elasticsearch进行交互.我正在尝试模拟elasticsearch-py函数,以便在不调用我的真实集群的情况下测试我的函数.
main.py
Escli继承了悬崖的App 阶级
class Escli(App):
_es = elasticsearch5.Elasticsearch()
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
我想要Escli._es.cluster.get_settings()返回我想要的东西(一个dict对象),以便不进行真正的HTTP调用,但它仍然继续这样做.
我知道的:
为了模拟实例方法,我必须做类似的事情
MagicMockObject.return_value.InstanceMethodName.return_value = ...
我无法修补,Escli._es.cluster.get_settings因为Python试图导入Escli为模块,这是无法工作的.所以我正在修补整个lib.
我拼命想把一些return_value地方放到一边,但我无法理解为什么我不能正确地嘲笑那件事.
你应该嘲笑你正在测试的地方。根据提供的示例,这意味着Escli您在模块中使用的类settings.py需要根据settings.py. 因此,更实际的是,您的patch调用内部看起来像这样setUp:
self.patcher = patch('escli.settings.Escli')
Run Code Online (Sandbox Code Playgroud)
有了这个,您现在可以根据测试的运行方式在正确的位置模拟您想要的内容。
此外,为了增强测试的稳健性,您可能需要考虑指定Elasticsearch您正在创建的实例,以验证您实际上正在调用与Elasticsearch. 考虑到这一点,您可以这样做:
self.patcher = patch('escli.settings.Escli', Mock(Elasticsearch))
Run Code Online (Sandbox Code Playgroud)
要详细了解 的确切含义spec,请查看文档中的补丁部分。
最后一点,如果您有兴趣探索pytest的伟大世界,可以创建一个pytest-elasticsearch插件来帮助您完成此任务。