Skip to content

Commit

Permalink
Merge pull request #8 from funnel-io/add-request-to-response
Browse files Browse the repository at this point in the history
Add request to response
  • Loading branch information
linus-funnel authored Feb 29, 2024
2 parents 2ce1623 + 4a456ff commit 2fcc726
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 33 deletions.
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ classifiers =
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
Topic :: Software Development :: Libraries
project_urls =
Bug Reports = https://github.com/funnel-io/requtests/issues
Expand Down
4 changes: 3 additions & 1 deletion src/requtests/fake_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ def close(self):
def send(self, request, **kwargs):
if self.assertions:
next(self.assertions)(request, **kwargs)
return next(self.responses)
response = next(self.responses)
response.request = request
return response


def _to_generator(element_or_collection):
Expand Down
46 changes: 23 additions & 23 deletions src/requtests/fake_request.py
Original file line number Diff line number Diff line change
@@ -1,50 +1,50 @@
from functools import partial
from requests import Session
from requtests.fake_adapter import FakeAdapter
from requtests.fake_response import fake_response


def fake_delete(*responses):
return partial(fake_request(*responses), "delete")
def fake_delete(*responses, assertions=None):
return partial(fake_request(*responses, assertions=assertions), "delete")


def fake_get(*responses):
return partial(fake_request(*responses), "get")
def fake_get(*responses, assertions=None):
return partial(fake_request(*responses, assertions=assertions), "get")


def fake_head(*responses):
return partial(fake_request(*responses), "head")
def fake_head(*responses, assertions=None):
return partial(fake_request(*responses, assertions=assertions), "head")


def fake_options(*responses):
return partial(fake_request(*responses), "options")
def fake_options(*responses, assertions=None):
return partial(fake_request(*responses, assertions=assertions), "options")


def fake_patch(*responses):
return partial(fake_request(*responses), "patch")
def fake_patch(*responses, assertions=None):
return partial(fake_request(*responses, assertions=assertions), "patch")


def fake_post(*responses):
return partial(fake_request(*responses), "post")
def fake_post(*responses, assertions=None):
return partial(fake_request(*responses, assertions=assertions), "post")


def fake_put(*responses):
return partial(fake_request(*responses), "put")
def fake_put(*responses, assertions=None):
return partial(fake_request(*responses, assertions=assertions), "put")


def fake_request_with_response(**response_config):
def fake_request_with_response(assertions=None, **response_config):
"""
Creates a request function that returns a response given the response_config.
"""
return fake_request(fake_response(**response_config))
return fake_request(fake_response(**response_config), assertions=assertions)


def fake_request(*responses):
def fake_request(*responses, assertions=None):
"""
Creates a request function that returns the supplied responses, one at a time.
Making a new request after the last response has been returned results in a StopIteration error.
"""
iterator = (response for response in responses)

def request(method, url, **kwargs):
return next(iterator)

return request
adapter = FakeAdapter(*responses, assertions=assertions)
session = Session()
session.get_adapter = lambda url: adapter
return session.request
13 changes: 8 additions & 5 deletions tests/fake_adapter_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@
def test_fake_adapter():
response = fake_response()
adapter = FakeAdapter(response)
request = PreparedRequest()
assert response.request is None
assert isinstance(adapter, BaseAdapter)
assert not adapter.closed
assert adapter.send(PreparedRequest()) == response
assert adapter.send(request) is response
assert adapter.close() is None
assert adapter.closed
assert response.request is request


def test_fake_adapter_with_assert_step():
Expand Down Expand Up @@ -47,8 +50,8 @@ def test_fake_adapter_with_multiple_responses():
assertions=assert_prepared_request(url=TEST_URL, body=TEST_DATA),
)
request = build_request(url=TEST_URL, body=TEST_DATA)
assert adapter.send(request) == response_1
assert adapter.send(request) == response_2
assert adapter.send(request) is response_1
assert adapter.send(request) is response_2


def test_fake_adapter_with_multiple_responses_and_assertions():
Expand All @@ -66,8 +69,8 @@ def test_fake_adapter_with_multiple_responses_and_assertions():
)
request_1 = build_request(url=TEST_URL, body=data_1)
request_2 = build_request(url=TEST_URL, body=data_2)
assert adapter.send(request_1) == response_1
assert adapter.send(request_2) == response_2
assert adapter.send(request_1) is response_1
assert adapter.send(request_2) is response_2


def test_fake_adapter_mounted_on_session():
Expand Down
12 changes: 11 additions & 1 deletion tests/fake_http_verbs_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,19 @@
}.items(),
)
def test_fake_http_method(func_name, method):
assertions_called = False

def assertions(prepared_request, **_):
nonlocal assertions_called
assertions_called = True
assert prepared_request.method == method.upper()

responses = [
fake_response(json={"tea": "brewing"}, status_code=418),
fake_response(json={"status": "I'm afraid I can't do that, Dave."}, status_code=405),
]

fake_http_method = getattr(requtests, func_name)(*responses)
fake_http_method = getattr(requtests, func_name)(*responses, assertions=assertions)
assert isinstance(fake_http_method, partial)
assert fake_http_method.args == (method,)

Expand All @@ -32,9 +39,12 @@ def test_fake_http_method(func_name, method):
json={"tea": "brewing"},
status_code=418,
)
assert assertions_called

assertions_called = False
assert_response(
fake_http_method("https://api.example.com/endpoint", params={"page": 2}),
json={"status": "I'm afraid I can't do that, Dave."},
status_code=405,
)
assert assertions_called
44 changes: 43 additions & 1 deletion tests/fake_request_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from requtests import fake_request_with_response, fake_response, fake_request
import pytest
from requests.models import PreparedRequest

from requtests import fake_request, fake_request_with_response, fake_response
from tests.test_utils import assert_response


Expand All @@ -21,6 +24,19 @@ def test_fake_request():
)


def test_fake_request_with_assertions():
assertions_called = False

def assertions(prepared_request, **_):
nonlocal assertions_called
assertions_called = True
assert isinstance(prepared_request, PreparedRequest)

response = fake_response(json={"some": "data"}, status_code=418)
fake_request(response, assertions=assertions)("get", "https://example.com")
assert assertions_called


def test_fake_request_with_response():
response_config = {
"json": {"some": "data"},
Expand All @@ -37,3 +53,29 @@ def test_fake_request_with_response():
headers={"some": "header"},
)
assert_response(response, **response_config)


def test_fake_request_with_response_with_assertions():
response_config = {
"json": {"some": "data"},
"reason": "some reason",
"status_code": 418,
"url": "some url",
}

assertions_called = False

def assertions(prepared_request, **_):
nonlocal assertions_called
assertions_called = True
assert isinstance(prepared_request, PreparedRequest)

request = fake_request_with_response(**response_config, assertions=assertions)
request(
"GET",
"https://api.example.com/endpoint",
params={"some": "param"},
headers={"some": "header"},
)

assert assertions_called
10 changes: 8 additions & 2 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@ def assertions(request, **kwargs):


def assert_response(
response, json=None, reason=None, status_code=200, text=None, url=None, headers={}
response,
json=None,
reason=None,
status_code=200,
text=None,
url=None,
headers={},
):
assert type(response) == Response
assert isinstance(response, Response)
assert response.status_code == status_code
assert response.reason == reason
assert response.url == url
Expand Down

0 comments on commit 2fcc726

Please sign in to comment.