¿Cómo puedo burlarme de las solicitudes y la respuesta?
Estoy intentando utilizar el paquete simulado de Pythons para simular requests
el módulo de Pythons. ¿Cuáles son las llamadas básicas para que pueda trabajar en el siguiente escenario?
En mi views.py, tengo una función que realiza una variedad de llamadas a request.get() con una respuesta diferente cada vez.
def myview(request):
res1 = requests.get('aurl')
res2 = request.get('burl')
res3 = request.get('curl')
En mi clase de prueba quiero hacer algo como esto pero no puedo entender las llamadas a métodos exactos
Paso 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'
Paso 2:
llama a mi vista
Paso 3:
verificar que la respuesta contenga 'respuesta a', 'respuesta b', 'respuesta c'
¿Cómo puedo completar el Paso 1 (burlarse del módulo de solicitudes)?
Así es como puedes hacerlo (puedes ejecutar este archivo tal cual):
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()
Nota importante: si su MyGreatClass
clase se encuentra en un paquete diferente, por ejemplo my.great.package
, debe simular my.great.package.requests.get
en lugar de simplemente 'request.get'. En ese caso, su caso de prueba se vería así:
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()
¡Disfrutar!
Intente utilizar la biblioteca de respuestas . Aquí hay un ejemplo de su documentación :
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"}'
Proporciona una gran comodidad en lugar de configurar todas las burlas usted mismo.
También está HTTPretty ... no es específico de requests
la biblioteca, es más poderoso en algunos aspectos, aunque descubrí que no se presta tan bien para inspeccionar las solicitudes que interceptó, lo cual responses
lo hace con bastante facilidad.
También está httmock .
Una nueva biblioteca que está ganando popularidad recientemente sobre la venerable requests
es httpx
, que agrega soporte de primera clase para asíncrono. Una biblioteca burlona para httpx es: https://github.com/lundberg/respx
Esto es lo que funcionó para mí:
import mock
@mock.patch('requests.get', mock.Mock(side_effect = lambda k:{'aurl': 'a response', 'burl' : 'b response'}.get(k, 'unhandled request %s'%k)))