Как я могу издеваться над запросами и ответом?
Я пытаюсь использовать питоны пробный пакет издеваться над питонами requests
модуль. Каковы основные вызовы, чтобы заставить меня работать в сценарии ниже?
В моем views.py, у меня есть функция, которая делает различные запросы.get () звонки с разным ответом каждый раз
def myview(request):
res1 = requests.get('aurl')
res2 = request.get('burl')
res3 = request.get('curl')
в моем тестовом классе я хочу сделать что-то вроде этого, но не могу выяснить точные вызовы метода
Шаг 1:
# Mock the requests module
# when mockedRequests.get('aurl') is called then return 'a response'
# when mockedRequests.get('burl') is called then return 'b response'
# when mockedRequests.get('curl') is called then return 'c response'
Шаг 2:
звонок мой посмотреть
Шаг 3:
Проверить ответ содержится 'ответ', 'ответ Б", "в ответ'
как я могу выполнить Шаг 1 (издеваясь над модулем запросов)?
7 ответов:
вот как вы можете это сделать (вы можете запустить этот файл как есть):
import requests import unittest from unittest import mock # This is the class we want to test class MyGreatClass: def fetch_json(self, url): response = requests.get(url) return response.json() # This method will be used by the mock to replace requests.get def mocked_requests_get(*args, **kwargs): class MockResponse: def __init__(self, json_data, status_code): self.json_data = json_data self.status_code = status_code def json(self): return self.json_data if args[0] == 'http://someurl.com/test.json': return MockResponse({"key1": "value1"}, 200) elif args[0] == 'http://someotherurl.com/anothertest.json': return MockResponse({"key2": "value2"}, 200) return MockResponse(None, 404) # Our test case class class MyGreatClassTestCase(unittest.TestCase): # We patch 'requests.get' with our own method. The mock object is passed in to our test case method. @mock.patch('requests.get', side_effect=mocked_requests_get) def test_fetch(self, mock_get): # Assert requests.get calls mgc = MyGreatClass() json_data = mgc.fetch_json('http://someurl.com/test.json') self.assertEqual(json_data, {"key1": "value1"}) json_data = mgc.fetch_json('http://someotherurl.com/anothertest.json') self.assertEqual(json_data, {"key2": "value2"}) json_data = mgc.fetch_json('http://nonexistenturl.com/cantfindme.json') self.assertIsNone(json_data) # We can even assert that our mocked method was called with the right parameters self.assertIn(mock.call('http://someurl.com/test.json'), mock_get.call_args_list) self.assertIn(mock.call('http://someotherurl.com/anothertest.json'), mock_get.call_args_list) self.assertEqual(len(mock_get.call_args_list), 3) if __name__ == '__main__': unittest.main()
Важное Замечание: если
MyGreatClass
класс живет в другом пакете, скажемmy.great.package
, вы должны издеваться надmy.great.package.requests.get
, а не просто запрос.получить'. В этом случае ваш тестовый случай будет выглядеть так:import unittest from unittest import mock from my.great.package import MyGreatClass # This method will be used by the mock to replace requests.get def mocked_requests_get(*args, **kwargs): # Same as above class MyGreatClassTestCase(unittest.TestCase): # Now we must patch 'my.great.package.requests.get' @mock.patch('my.great.package.requests.get', side_effect=mocked_requests_get) def test_fetch(self, mock_get): # Same as above if __name__ == '__main__': unittest.main()
наслаждайтесь!
попробуйте использовать ответы библиотека:
import responses import requests @responses.activate def test_simple(): responses.add(responses.GET, 'http://twitter.com/api/1/foobar', json={'error': 'not found'}, status=404) resp = requests.get('http://twitter.com/api/1/foobar') assert resp.json() == {"error": "not found"} assert len(responses.calls) == 1 assert responses.calls[0].request.url == 'http://twitter.com/api/1/foobar' assert responses.calls[0].response.text == '{"error": "not found"}'
обеспечивает довольно хорошее удобство по сравнению с настройкой все издеваются над собой
там же HTTPretty:
это не относится к
requests
библиотека, более мощная в некоторых отношениях, хотя я обнаружил, что она не так хорошо поддается проверке запросов, которые она перехватила, чтоresponses
достаточно легкои httmock:
вот что сработало для меня:
import mock @mock.patch('requests.get', mock.Mock(side_effect = lambda k:{'aurl': 'a response', 'burl' : 'b response'}.get(k, 'unhandled request %s'%k)))
Я запросы-mock для написания тестов для отдельных модулей:
# module.py import requests class A(): def get_response(self, url): response = requests.get(url) return response.text
и тесты:
# tests.py import requests_mock import unittest from module import A class TestAPI(unittest.TestCase): @requests_mock.mock() def test_get_response(self, m): a = A() m.get('http://aurl.com', text='a response') self.assertEqual(a.get_response('http://aurl.com'), 'a response') m.get('http://burl.com', text='b response') self.assertEqual(a.get_response('http://burl.com'), 'b response') m.get('http://curl.com', text='c response') self.assertEqual(a.get_response('http://curl.com'), 'c response') if __name__ == '__main__': unittest.main()
вот как вы издеваетесь над запросами.сообщение, измените его на свой метод http
@patch.object(requests, 'post') def your_test_method(self, mockpost): mockresponse = Mock() mockpost.return_value = mockresponse mockresponse.text = 'mock return' #call your target method now
Если вы хотите издеваться над поддельным ответом, другой способ сделать это-просто создать экземпляр базового класса HttpResponse, например:
from django.http.response import HttpResponseBase self.fake_response = HttpResponseBase()
один из возможных способов обойти запросы-использовать библиотеку betamax, она записывает все запросы, и после этого, если вы сделаете запрос в том же url с теми же параметрами, betamax будет использовать записанный запрос, я использую его для тестирования веб-искателя, и это сэкономит мне много времени.
import os import requests from betamax import Betamax from betamax_serializers import pretty_json WORKERS_DIR = os.path.dirname(os.path.abspath(__file__)) CASSETTES_DIR = os.path.join(WORKERS_DIR, u'resources', u'cassettes') MATCH_REQUESTS_ON = [u'method', u'uri', u'path', u'query'] Betamax.register_serializer(pretty_json.PrettyJSONSerializer) with Betamax.configure() as config: config.cassette_library_dir = CASSETTES_DIR config.default_cassette_options[u'serialize_with'] = u'prettyjson' config.default_cassette_options[u'match_requests_on'] = MATCH_REQUESTS_ON config.default_cassette_options[u'preserve_exact_body_bytes'] = True class WorkerCertidaoTRT2: session = requests.session() def make_request(self, input_json): with Betamax(self.session) as vcr: vcr.use_cassette(u'google') response = session.get('http://www.google.com')