У меня проблема с пониманием того, как работает mock и как писать юнит-тесты с фиктивными объектами. Я хотел имитировать внешний вызов API каждый раз, когда моя модель вызывает метод save(). Мой код: models.py
from . import utils
class Book(Titleable, Isactiveable, Timestampable, IsVoidable, models.Model):
title
orig_author
orig_title
isbn
def save(self, *args, **kwargs):
if self.isbn:
google_data = utils.get_original_title_and_name(self.isbn)
if google_data:
self.original_author = google_data['author']
self.original_title = google_data['title']
super().save(*args, **kwargs)
utils.py
def get_original_title_and_name(isbn, **kawargs):
isbn_search_string = 'isbn:{}'.format(isbn)
payload = {
'key': GOOGLE_API_KEY,
'q': isbn_search_string,
'printType': 'books',
}
r = requests.get(GOOGLE_API_URL, params=payload)
response = r.json()
if 'items' in response.keys():
title = response['items'][THE_FIRST_INDEX]['volumeInfo']['title']
author = response['items'][THE_FIRST_INDEX]['volumeInfo']['authors'][THE_FIRST_INDEX]
return {
'title': title,
'author': author
}
else:
return None
Я начал читать документы и писать тест:
test.py
:
from unittest import mock
from django.test import TestCase
from rest_framework import status
from .constants import THE_FIRST_INDEX, GOOGLE_API_URL, GOOGLE_API_KEY
class BookModelTestCase(TestCase):
@mock.patch('requests.get')
def test_get_original_title_and_name_from_google_api(self, mock_get):
# Define new Mock object
mock_response = mock.Mock()
# Define response data from Google API
expected_dict = {
'kind': 'books#volumes',
'totalItems': 1,
'items': [
{
'kind': 'books#volume',
'id': 'IHxXBAAAQBAJ',
'etag': 'B3N9X8vAMWg',
'selfLink': 'https://www.googleapis.com/books/v1/volumes/IHxXBAAAQBAJ',
'volumeInfo': {
'title': "Alice's Adventures in Wonderland",
'authors': [
'Lewis Carroll'
]
}
}
]
}
# Define response data for my Mock object
mock_response.json.return_value = expected_dict
mock_response.status_code = 200
# Define response for the fake API
mock_get.return_value = mock_response
Во-первых, я не могу правильно написать target
вместо @mock.patch
. Если определить target
как utuls.get_original_title_and_name.requests.get
, я получу ModuleNotFoundError
. Также я не могу понять, как сделать поддельный вызов внешнего API и проверить полученные данные (обязательно ли это, если я уже определил mock_response.json.return_value = expected_dict?
) и убедиться, что мой метод save () работает хорошо?
Как мне написать тест для этих случаев? Может ли кто-нибудь объяснить мне этот случай?
model.save()
. Я бы предпочел использовать асинхронную очередь для таких вещей. - person bruno desthuilliers   schedule 03.05.2018utils.get_original_title_and_name.requests.get
, исправьтеutils.requests.get
. - person hoefling   schedule 03.05.2018ModuleNotFoundError
. Нет ли опечатки вutuls.get_original_title_and_name.requests.get
(utuls -> utils) - person Andrew_Lvov   schedule 03.05.2018