#python #unit-testing #mocking #python-requests #flask-restful
#python #модульное тестирование #издевательство #python-запросы #flask-restful
Вопрос:
У меня есть Flask views.py модульный тест, который вызывает другой REST API. Как я могу конкретно имитировать один из запросов?
Причина в том, что один из запросов вызовет некоторые операции, такие как фиксация в базе данных, перезапись в файл и т.д., Если код состояния равен 200. Я хочу проверить, вернет ли код состояния 200. Если да, я хочу предотвратить последующие операции в модульном тестировании, а если нет, то это все равно не повлияет ни на одну последующую операцию, так что не беспокойтесь.
Я также хочу, чтобы высмеянный запрос вообще не влиял на запрос приложения Flask, т. Е. Запрос приложения Flask не высмеивается.
project/views.py
from flask import Flask
from project.another_dir.another_script import another_function
app = Flask(__name__)
@app.route('/api/abcde', methods=['POST'])
def post_something():
another_function()
project/another_dir/another_script.py
import requests
def another_function():
response = requests.post(<some_url>) # this is the "requests" I want to mock
if response.status_code == 200:
# server working properly, commit database transaction / write to a file / trigger some other functions / ...
else:
# something's wrong with the server, send error for exception handling
Модульный тест
from unittest.mock import Mock
import pytest
headers = {'Authorization': 'Basic akd39K045Pw=='}
data = "some_data"
@pytest.fixture
def client():
app.testing = True
client = app.test_client()
return client
@pytest.mark.parametrize("h, d, status_code", [
(None, None, 401), # no auth header, no data
(None, data, 401), # no auth header
(headers, data, 200) # with auth header and data
])
def test_views_post_something(client, h, d, status_code):
##### This is what I want to mock to avoid actually committing to db
# from project.another_dir.another_script import requests
# mock_request = Mock()
# requests = mock_request
##### But no luck
response = client.post('/api/abcde', headers=h, data=d)
assert response.status_code == status_code
Ответ №1:
Вы пробовали pook и unmock? Они служат для разных вариантов использования, но в данном случае, похоже, что pook подходит лучше. Pook работает хорошо, если запрос, который вы имитируете, не сильно изменится и относится к частному / внутреннему API
Другой вариант — использовать такой инструмент, как docker-compose
, для создания эфемерного стека с выбранной вами базой данных. Таким образом, вы можете позволить запросу выполняться, не затрагивая никаких хрупких ресурсов, но это, как правило, происходит медленнее и подвержено ошибкам, если вы пытаетесь воссоздать сложные состояния. Обычно я начинаю с более скромного подхода, такого как pook
или unmock
, а затем создаю эфемерный стек для наиболее критически важных тестов.