gpt4 book ai didi

python - Unittest Django : Mock external API, 什么是正确的方法?

转载 作者:太空狗 更新时间:2023-10-30 02:25:09 24 4
gpt4 key购买 nike

我在理解模拟如何工作以及如何使用模拟对象编写单元测试时遇到问题。每当我的模型调用 save() 方法时,我都想模拟一个外部 api 调用。我的代码:模型.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

我开始阅读文档并编写测试:

测试.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

首先,我无法为@mock.patch 正确编写target。如果将 target 定义为 utuls.get_original_title_and_name.requests.get,我将得到 ModuleNotFoundError。此外,我不明白如何对外部 API 进行虚假调用并验证接收到的数据(如果我已经定义了 mock_response.json.return_value = expected_dict?,是否有必要)并验证我的save() 方法效果好吗?

如何为这种情况编写测试?谁能给我解释一下这个案例?

最佳答案

您应该模拟被测代码的直接合作者。对于 Book,它将是 utils。对于 utils,这将是 requests

所以对于 BookModelTestCase:

class BookModelTestCase(TestCase):

@mock.patch('app.models.utils')
def test_save_book_calls_google_api(self, mock_utils):
mock_utils.get_original_title_and_name.return_value = {
'title': 'Google title',
'author': 'Google author'
}

book = Book(
title='Some title',
isbn='12345'
)
book.save()

self.assertEqual(book.title, 'Google title')
self.assertEqual(book.author, 'Google author')
mock_utils.get_original_title_and_name.assert_called_once_with('12345')

然后您可以创建一个单独的测试用例来测试get_original_title_and_name:

class GetOriginalTitleAndNameTestCase(TestCase):

@mock.patch('app.utils.requests.get')
def test_get_original_title_and_name_from_google_api(self, mock_get):
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

# Call the function
result = get_original_title_and_name(12345)

self.assertEqual(result, {
'title': "Alice's Adventures in Wonderland",
'author': 'Lewis Carroll'
})
mock_get.assert_called_once_with(GOOGLE_API_URL, params={
'key': GOOGLE_API_KEY,
'q': 'isbn:12345',
'printType': 'books',
})

关于python - Unittest Django : Mock external API, 什么是正确的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50157543/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com