#python #mocking #pytest
Вопрос:
В проекте Python я использую асинхронный клиент Elasticsearch, подобный этому:
pip install elasticsearch[async]
from elasticsearch import AsyncElasticsearch
async def es_search(...):
es_client = AsyncElasticsearch(url, timeout=30)
es_response = await es_client.search(...)
return es_response
Это работает, как и ожидалось.
Теперь я хочу написать модульные тесты и поиздеваться AsyncElasticsearch
над поведением клиента с помощью pytest
«s mock
«.
Я попытался написать базовый тест макет, подобный этому (где test_app
и mocker
вводятся приспособления для тестирования).:
def test_es_search(test_app, mocker):
mocker.patch('elasticsearch.AsyncElasticsearch.search', return_value={"data": "foobar"})
result = es_search()
assert result == {"data": "foobar"}
При запуске моего теста pytest
происходит сбой с этой ошибкой:
thing = <class 'elasticsearch._async.client.AsyncElasticsearch'>
comp = 'cluster', import_path = 'elasticsearch.AsyncElasticsearch.cluster'
def _dot_lookup(thing, comp, import_path):
try:
return getattr(thing, comp)
except AttributeError:
> __import__(import_path)
E ModuleNotFoundError: No module named 'elasticsearch.AsyncElasticsearch'
После просмотра установленных путей lib ( elasticsearch[async]
) я обнаружил, что «реальным» путем для этого AsyncElasticsearch
класса является « elasticsearch._async.client.AsyncElasticsearch
«. Поэтому я обновил свой макет, чтобы использовать этот путь:
def test_es_search(test_app, mocker):
mocker.patch('elasticsearch._async.client.AsyncElasticsearch.search', return_value={"data": "foobar"})
result = es_search()
assert result == {"data": "foobar"}
Но то же самое, pytest
не удалось с:
thing = <class 'elasticsearch._async.client.AsyncElasticsearch'>
comp = 'cluster'
import_path = 'elasticsearch._async.client.AsyncElasticsearch.cluster'
def _dot_lookup(thing, comp, import_path):
try:
return getattr(thing, comp)
except AttributeError:
> __import__(import_path)
E ModuleNotFoundError: No module named 'elasticsearch._async.client.AsyncElasticsearch'
Вот мой вопрос: как я могу издеваться над этим классом, который добавляется в мой проект в качестве «дополнительной» зависимости от pip ? Какой путь я должен использовать, mocker.patch()
чтобы высмеять это ? Я что-то упускаю ?
Комментарии:
1. имитируйте, куда вы его импортируете вместо этого. поэтому, если вызывается скрипт, который запускает этот импорт
foo.py
, вы должны просто выполнятьmocker.patch("foo.AsyncElasticsearch")