Я хочу провести модульное тестирование модуля, взаимодействующего с API, созданным с помощью Django Rest Framework. Для этого я использую библиотеку Python Mock. Поскольку у меня нет опыта использования mocks для тестирования взаимодействия с API, у меня проблемы.
Функция, которая отправляет объект в конечную точку API, выглядит так (вкратце):
def send_experiment_to_portal(experiment: Experiment):
rest = RestApiClient()
if not rest.active:
return None
# general params
params = {"nes_id": str(experiment.id),
"title": experiment.title,
"description": experiment.description,
"data_acquisition_done":
str(experiment.data_acquisition_is_concluded),
"project_url": experiment.source_code_url,
"ethics_committee_url": experiment.ethics_committee_project_url
}
action_keys = ['experiments', 'create']
portal_experiment = rest.client.action(
rest.schema, action_keys, params=params,
)
return portal_experiment
RestAPIClient
- это класс, который аутентифицируется в API:
class RestApiClient(object):
client = None
schema = None
active = False
def __init__(self):
auth = coreapi.auth.BasicAuthentication(
username=settings.PORTAL_API['USER'],
password=settings.PORTAL_API['PASSWORD']
)
self.client = coreapi.Client(auth=auth)
try:
url = settings.PORTAL_API['URL'] + \
(
':' + settings.PORTAL_API['PORT'] if
settings.PORTAL_API['PORT'] else ''
) \
+ '/api/schema/'
self.schema = self.client.get(url)
self.active = True
except:
self.active = False
Класс RestApiClient
использует клиентский модуль coreapi
для подключения к API.
Итак, в конце я начинаю с проверки, имеет ли аргумент params
в rest.client.action
ключи / значения, которые предусмотрены API с использованием библиотеки python mock.
Я начинаю писать начальный тест как:
class PortalAPITest(TestCase):
@patch('experiment.portal.RestApiClient')
def test_send_experiment_to_portal(self, mockRestApiClientClass):
research_project = ObjectsFactory.create_research_project()
experiment = ObjectsFactory.create_experiment(research_project)
result = send_experiment_to_portal(experiment)
Поэтому, когда я отлаживаю тест, заглядывая внутрь функции send_experiment_to_portal
rest.client.action.call_args
имеет значение:
call(<MagicMock name='RestApiClient().schema' id='139922756141240'>, ['expreiments', 'create'], params={'description': 'Descricao do Experimento-Update', 'ethics_committee_url': None, 'project_url': None, 'title': 'Experimento-Update', 'nes_id': '37', 'data_acquisition_done': 'False'})
Но mockRestApiClientClass.client.action.call_args
имеет None
. Я подозреваю, что я делаю неправильно. Я должен высмеивать rest.client.action, а не класс RestApiClient
.
Попытка использовать result
значение тоже не работает.
Значение результата
<MagicMock name='RestApiClient().client.action()' id='139821809672144'>
и result.call_args
тоже None
.
Но как это сделать? Как получить насмешливый rest
экземпляр вне функции send_experiment_to_portal
?