Create a functioning Response object
Question:
For testing purposes I’m trying to create a Response() object in python but it proves harder then it sounds.
i tried this:
from requests.models import Response
the_response = Response()
the_response.code = "expired"
the_response.error_type = "expired"
the_response.status_code = 400
but when I attempted the_response.json()
i got an error because the function tries to get len(self.content)
and a.content
is null.
So I set a._content = "{}"
but then I get an encoding error, so I have to change a.encoding
, but then it fails to decode the content….
this goes on and on. Is there a simple way to create a Response object that’s functional and has an arbitrary status_code and content?
Answers:
That because the _content
attribute on the Response
objects (on python3) has to be bytes and not unicodes.
Here is how to do it:
from requests.models import Response
the_response = Response()
the_response.code = "expired"
the_response.error_type = "expired"
the_response.status_code = 400
the_response._content = b'{ "key" : "a" }'
print(the_response.json())
Just use the responses
library to do it for you:
import responses
@responses.activate
def test_my_api():
responses.add(responses.GET, 'http://whatever.org',
json={}, status=400)
...
This has the advantage that it intercepts a real request, rather than having to inject a response somewhere.
Create a mock
object, rather than trying to build a real one:
from unittest.mock import Mock
from requests.models import Response
the_response = Mock(spec=Response)
the_response.json.return_value = {}
the_response.status_code = 400
Providing a spec
ensures that the mock will complain if you try to access methods and attributes a real Response
doesn’t have.
Another approach by using the requests_mock
library, here with the provided fixture:
import requests
def test_response(requests_mock):
requests_mock.register_uri('POST', 'http://test.com/', text='data', headers={
'X-Something': '1',
})
response = requests.request('POST', 'http://test.com/', data='helloworld')
...
For testing purposes I’m trying to create a Response() object in python but it proves harder then it sounds.
i tried this:
from requests.models import Response
the_response = Response()
the_response.code = "expired"
the_response.error_type = "expired"
the_response.status_code = 400
but when I attempted the_response.json()
i got an error because the function tries to get len(self.content)
and a.content
is null.
So I set a._content = "{}"
but then I get an encoding error, so I have to change a.encoding
, but then it fails to decode the content….
this goes on and on. Is there a simple way to create a Response object that’s functional and has an arbitrary status_code and content?
That because the _content
attribute on the Response
objects (on python3) has to be bytes and not unicodes.
Here is how to do it:
from requests.models import Response
the_response = Response()
the_response.code = "expired"
the_response.error_type = "expired"
the_response.status_code = 400
the_response._content = b'{ "key" : "a" }'
print(the_response.json())
Just use the responses
library to do it for you:
import responses
@responses.activate
def test_my_api():
responses.add(responses.GET, 'http://whatever.org',
json={}, status=400)
...
This has the advantage that it intercepts a real request, rather than having to inject a response somewhere.
Create a mock
object, rather than trying to build a real one:
from unittest.mock import Mock
from requests.models import Response
the_response = Mock(spec=Response)
the_response.json.return_value = {}
the_response.status_code = 400
Providing a spec
ensures that the mock will complain if you try to access methods and attributes a real Response
doesn’t have.
Another approach by using the requests_mock
library, here with the provided fixture:
import requests
def test_response(requests_mock):
requests_mock.register_uri('POST', 'http://test.com/', text='data', headers={
'X-Something': '1',
})
response = requests.request('POST', 'http://test.com/', data='helloworld')
...