Skip to content

Commit

Permalink
response callback work
Browse files Browse the repository at this point in the history
  • Loading branch information
jvanasco committed Jun 20, 2017
1 parent b1af5df commit 5dd9196
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGES
Expand Up @@ -2,6 +2,7 @@ Unreleased
----------

- Allow empty list/dict as json object (GH-100)
- Added `response_callback`

0.5.1
-----
Expand Down
28 changes: 28 additions & 0 deletions README.rst
Expand Up @@ -188,3 +188,31 @@ You can also use ``assert_all_requests_are_fired`` to add multiple responses for
assert resp.status_code == 500
resp = requests.get('http://twitter.com/api/1/foobar')
assert resp.status_code == 200
Using a callback to modify the response
---------------------------------------

If you use customized processing in `requests` via subclassing/mixins, or if you
have library tools that interact with `requests` at a low level, you may need
to add extended processing to the mocked Response object to fully simlulate the
environment for your tests. A `response_callback` can be used, which will be
wrapped by the library before being returned to the caller. The callback
accepts a `response` as it's single argument, and is expected to return a
single `response` object.


.. code-block:: python
import responses
import requests
def response_callback(resp):
resp.callback_processed = True
return resp
with responses.RequestsMock(response_callback=response_callback) as m:
m.add(responses.GET, 'http://example.com', body=b'test')
resp = requests.get('http://example.com')
assert resp.text == "test"
assert hasattr(resp, 'callback_processed')
assert resp.callback_processed is True
8 changes: 7 additions & 1 deletion responses.py
Expand Up @@ -118,11 +118,14 @@ class RequestsMock(object):
PATCH = 'PATCH'
POST = 'POST'
PUT = 'PUT'
response_callback = None

def __init__(self, assert_all_requests_are_fired=True):
def __init__(self, assert_all_requests_are_fired=True,
response_callback=None):
self._calls = CallList()
self.reset()
self.assert_all_requests_are_fired = assert_all_requests_are_fired
self.response_callback = response_callback

def reset(self):
self._urls = []
Expand Down Expand Up @@ -230,6 +233,7 @@ def _has_strict_url_match(self, url, other):

def _on_request(self, adapter, request, **kwargs):
match = self._find_match(request)
resp_callback = self.response_callback
# TODO(dcramer): find the correct class for this
if match is None:
error_msg = 'Connection refused: {0} {1}'.format(request.method,
Expand All @@ -238,6 +242,7 @@ def _on_request(self, adapter, request, **kwargs):
response.request = request

self._calls.add(request, response)
response = resp_callback(response) if resp_callback else response
raise response

if 'body' in match and isinstance(match['body'], Exception):
Expand Down Expand Up @@ -283,6 +288,7 @@ def _on_request(self, adapter, request, **kwargs):
except (KeyError, TypeError):
pass

response = resp_callback(response) if resp_callback else response
self._calls.add(request, response)

return response
Expand Down
16 changes: 16 additions & 0 deletions test_responses.py
Expand Up @@ -373,6 +373,22 @@ def run():
assert_reset()


def test_response_callback():
"""adds a callback to decorate the response, then checks it"""
def run():
def response_callback(resp):
resp._is_mocked = True
return resp
with responses.RequestsMock(response_callback=response_callback) as m:
m.add(responses.GET, 'http://example.com', body=b'test')
resp = requests.get('http://example.com')
assert resp.text == "test"
assert hasattr(resp, '_is_mocked')
assert resp._is_mocked is True
run()
assert_reset()


def test_assert_all_requests_are_fired():
def run():
with pytest.raises(AssertionError) as excinfo:
Expand Down

0 comments on commit 5dd9196

Please sign in to comment.