Издевательские звонки - PullRequest
0 голосов
/ 24 мая 2018

Я пишу CLI для взаимодействия сasticsearch, используя библиотекуasticsearch-py.Я пытаюсь смоделировать функцииasticsearch-py, чтобы протестировать мои функции без вызова моего реального кластера.

Я прочитал этот вопрос и этот , но я все ещене понимаю.

main.py

Escli наследуется от класса скалы App

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, но я не могу понять, почему я не могу насмехаться над этим должным образом.

1 Ответ

0 голосов
/ 25 мая 2018

Вы должны насмехаться над тем, где вы тестируете.На основании приведенного примера это означает, что класс Escli, который вы используете в модуле settings.py, должен быть смоделирован относительно settings.py.Таким образом, на практике ваш patch вызов будет выглядеть следующим образом внутри setUp:

self.patcher = patch('escli.settings.Escli')

С этим вы теперь высмеиваете, что хотите, в нужном месте в зависимости от того, как выполняются ваши тесты.,

Кроме того, чтобы повысить надежность тестирования, вы можете рассмотреть возможность создания экземпляра Elasticsearch, который вы создаете, чтобы проверить, действительно ли вы вызываете допустимые методы, соответствующие Elasticsearch.Имея это в виду, вы можете сделать что-то вроде этого, вместо этого:

self.patcher = patch('escli.settings.Escli', Mock(Elasticsearch))

Чтобы прочитать немного больше о том, что именно подразумевается под spec, проверьте раздел patch вдокументация.

В качестве последнего замечания, если вы заинтересованы в изучении великого мира pytest , существует плагин pytest -asticsearch , созданный для этой цели.

...