Skip to content

Commit

Permalink
feat: control request assertion on callback level
Browse files Browse the repository at this point in the history
  • Loading branch information
felixscherz committed May 14, 2024
1 parent 9e1661f commit 815a16a
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 7 deletions.
27 changes: 20 additions & 7 deletions pytest_httpx/_httpx_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def __init__(self) -> None:
Optional[httpx.Response], Awaitable[Optional[httpx.Response]]
],
],
bool,
]
] = []

Expand All @@ -36,6 +37,7 @@ def add_response(
html: Optional[str] = None,
stream: Any = None,
json: Any = None,
assert_requested=True,
**matchers: Any,
) -> None:
"""
Expand Down Expand Up @@ -73,14 +75,17 @@ def response_callback(request: httpx.Request) -> httpx.Response:
stream=stream,
)

self.add_callback(response_callback, **matchers)
self.add_callback(
response_callback, assert_requested=assert_requested, **matchers
)

def add_callback(
self,
callback: Callable[
[httpx.Request],
Union[Optional[httpx.Response], Awaitable[Optional[httpx.Response]]],
],
assert_requested=True,
**matchers: Any,
) -> None:
"""
Expand All @@ -97,9 +102,13 @@ def add_callback(
:param match_content: Full HTTP body identifying the request(s) to match. Must be bytes.
:param match_json: JSON decoded HTTP body identifying the request(s) to match. Must be JSON encodable.
"""
self._callbacks.append((_RequestMatcher(**matchers), callback))
self._callbacks.append(
(_RequestMatcher(**matchers), callback, assert_requested)
)

def add_exception(self, exception: Exception, **matchers: Any) -> None:
def add_exception(
self, exception: Exception, assert_requested=True, **matchers: Any
) -> None:
"""
Raise an exception if a request match.
Expand All @@ -119,7 +128,9 @@ def exception_callback(request: httpx.Request) -> None:
exception.request = request
raise exception

self.add_callback(exception_callback, **matchers)
self.add_callback(
exception_callback, assert_requested=assert_requested, **matchers
)

def _handle_request(
self,
Expand Down Expand Up @@ -166,7 +177,7 @@ def _explain_that_no_response_was_found(
real_transport: Union[httpx.BaseTransport, httpx.AsyncBaseTransport],
request: httpx.Request,
) -> str:
matchers = [matcher for matcher, _ in self._callbacks]
matchers = [matcher for matcher, _, _ in self._callbacks]

message = f"No response can be found for {RequestDescription(real_transport, request, matchers)}"

Expand All @@ -188,7 +199,7 @@ def _get_callback(
]:
callbacks = [
(matcher, callback)
for matcher, callback in self._callbacks
for matcher, callback, _ in self._callbacks
if matcher.match(real_transport, request)
]

Expand Down Expand Up @@ -260,7 +271,9 @@ def reset(self, assert_all_responses_were_requested: bool) -> None:

def _reset_callbacks(self) -> list[_RequestMatcher]:
callbacks_not_executed = [
matcher for matcher, _ in self._callbacks if not matcher.nb_calls
matcher
for matcher, _, assert_requested in self._callbacks
if not matcher.nb_calls and assert_requested
]
self._callbacks.clear()
return callbacks_not_executed
Expand Down
20 changes: 20 additions & 0 deletions tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,26 @@ def unused(*args, **kwargs):
result.assert_outcomes(passed=1)


def test_httpx_mock_unused_single_unused_callback(testdir: Testdir) -> None:
"""
Unused callbacks should not fail test case if assert_all_responses_were_requested fixture is set to False.
"""
testdir.makepyfile(
"""
import pytest
def test_httpx_mock_unused_callback_without_assertion(httpx_mock):
def unused(*args, **kwargs):
pass
httpx_mock.add_callback(unused, assert_requested=False)
"""
)
result = testdir.runpytest()
result.assert_outcomes(passed=1)


def test_httpx_mock_non_mocked_hosts_sync(testdir: Testdir) -> None:
"""
Non mocked hosts should go through while other requests should be mocked.
Expand Down

0 comments on commit 815a16a

Please sign in to comment.