Тестирование модулей Python или код, имеющих любые внешние вызовы, такие как сторонние вызовы API или вызовы базы данных, могут затруднить. Это где издевательства полезны.
Макеты обычно используются, когда:
- Вызов третьей сторонней API является избыточным в сценариях тестирования (но требуется в фактической версии производства) I.e. Данные из внешнего сервиса не часто меняются, однако, что накладные перековы HTTP-адресов результатов.
- Звонение третьей стороной – это только премиум-подписка (оплачена) I.e. У него нет среды тестирования жгута
- Ответ от третьей партии не может быть легко контролируется, просто изменив входные данные I.E. Имитация ответов в угол, полученные внешние API.
Существует несколько способов внедрения издевательства ниже, является простым внедрением издевательства HTTP-сервиса, используя Unittest.mock Библиотека Отказ
MOCK HTTP-запрос
Предположим, что есть сервис, который дает температуру обратно, когда их запрошены с городом или местоположением:
Пример API “Get” выводится, как видно на браузере
Типичная библиотека вызывающих в клиентском коде будет реализовать что-то вроде:
import requests import json class ExternalServiceUtility: def __init__(self): super().__init__() # Function to make call to external service def get_current_temperature_using_service(self, location): _temperature_service_url = "http://127.0.0.1:5001/gettemparature/{0}" #in real life would be from configuration formatted_url = _temperature_service_url.format(location) current_temperature = None try: response_obj = requests.get(formatted_url) # check if we got a valid response if response_obj.status_code != 200: #some logging return current_temperature # parse the response response_json = response_obj.json() current_temperature = response_json["Temperature"] return current_temperature except Exception as ex: # some logging and handling return current_temperature
И метод использования этой библиотеки будет выглядеть так:
from externalserviceutility import ExternalServiceUtility def get_actual_temperature(location): extutil = ExternalServiceUtility() temperature = extutil.get_current_temperature_using_service(location) print(temperature) get_actual_temperature("Regina")
Здесь мы можем захотеть проверить приложение, не вызывая конечную точку HTTP. Следовательно, реализация издевательства будет выглядеть ниже.
from externalserviceutility import ExternalServiceUtility import requests from unittest.mock import patch import json def alternate_mock_method(args): data = '{"Temperature": 100, "Location": "Toronto", "Datetime": "2020-07-23", "Units": "Celsius"}' r = requests.Response() r.status_code = 200 def json_func(): return json.loads(data) r.json = json_func return r @patch('requests.get',side_effect=alternate_mock_method) def get_temperature_with_mock(location, args): extutil = ExternalServiceUtility() temperature = extutil.get_current_temperature_using_service(location) print(temperature) get_temperature_with_mock("Regina")
Те же реализация может быть сделана для других глаголов в библиотеке, скажем, requests.post.post.
Детали реализации:
- Включают в себя Unittest Myck Library и импорт на вершине
- Украсьте метод, используя «патч». Все призывы к способу, объявленному в первом параметре патча, будут перенаправлены на имя функции, объявленного в качестве второго параметра i.e. Side_effect.
- Теперь вместо того, чтобы сделать вызовы на внешнюю службу, реализация «alternate_Mock_Method» будет вызываться для каждого запроса. Получите запрос со всем дочерним кодом метода «get_temperature_with_mock». Метод. Способ, украшенный атрибутом патча.
- Обратите внимание, что метод # get_temperature_with_mock требует дополнительного параметра в конце синтаксиса.
Осторожно: обратите внимание, что все звонки на requests.get . В рамках кодовой структуры дерева в издевательственном методе будет перенаправлена на заказ на заказ.
Оригинал: “https://dev.to/sridharanprasanna/mock-external-dependencies-in-python-2kac”