Skip to content

Commit

Permalink
Default behavior is now to not rely on the code to fail on raised Tim…
Browse files Browse the repository at this point in the history
…eout, but instead fail at teardown if unexpected requests were issued
  • Loading branch information
Colin-b committed Sep 20, 2024
1 parent 227d684 commit 5cf03e3
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 91 deletions.
9 changes: 3 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]
### Changed
- Tests will now fail at teardown by default if some requests were issued but were not matched.
- This behavior can be changed thanks to the new ``pytest.mark.httpx_mock(assert_all_requests_were_expected=False)`` option.
- The `httpx_mock` fixture is now configured using a marker (many thanks to [`Frazer McLean`](https://github.com/RazerM)).
```python
# Apply marker to whole module
Expand All @@ -18,15 +20,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
```
- The following options are available:
- `assert_all_responses_were_requested` (boolean), defaulting to `True`.
- `assert_all_requests_were_expected` (boolean), defaulting to `False`.
- `assert_all_requests_were_expected` (boolean), defaulting to `True`.
- `non_mocked_hosts` (iterable), defaulting to an empty list, meaning all hosts are mocked.
- `httpx_mock.reset` do not expect any parameter anymore and will only reset the mock state (no assertions will be performed).

### Added
- It is now possible to ensure that all requests were expected. Use `pytest.mark.httpx_mock(assert_all_requests_were_expected=True)`.
- This is especially useful if your code is swallowing exceptions that are raised by `httpx_mock` when receiving an unexpected request.
- Note that the default behavior will change to `True` in the next release. Set it to `False` if you want to keep previous behavior.

### Removed
- `pytest` `7` is not supported anymore (`pytest` `8` has been out for 9 months already).
- `assert_all_responses_were_requested` fixture is not available anymore, use `pytest.mark.httpx_mock(assert_all_responses_were_requested=False)` instead.
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,7 @@ import pytest
from pytest_httpx import HTTPXMock


@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_timeout(httpx_mock: HTTPXMock):
with httpx.Client() as client:
with pytest.raises(httpx.TimeoutException):
Expand All @@ -572,17 +573,16 @@ def test_timeout(httpx_mock: HTTPXMock):
The best way to ensure the content of your requests is still to use the `match_headers` and / or `match_content` parameters when adding a response.
In the same spirit, ensuring that no request was issued does not necessarily require any code.

Note that default behavior is to send an `httpx.TimeoutException` in case no response can be found.
However, should your test swallow exceptions, you can use the `httpx_mock` marker to ensure that only expected requests have been issued:
Note that default behavior is to assert that all requests were expected. You can turn this off (at your own risk of not spotting regression in your code base) using the `httpx_mock` marker:

```python
import pytest

# For whole module
pytestmark = pytest.mark.httpx_mock(assert_all_requests_were_expected=True)
pytestmark = pytest.mark.httpx_mock(assert_all_requests_were_expected=False)

# For specific test
@pytest.mark.httpx_mock(assert_all_requests_were_expected=True)
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_something(httpx_mock):
...
```
Expand Down
3 changes: 1 addition & 2 deletions pytest_httpx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,5 @@ async def mocked_handle_async_request(
def pytest_configure(config: Config) -> None:
config.addinivalue_line(
"markers",
"httpx_mock(*, assert_all_responses_were_requested=True, "
"non_mocked_hosts=[]): Configure httpx_mock fixture.",
"httpx_mock(*, assert_all_responses_were_requested=True, assert_all_requests_were_expected=True, non_mocked_hosts=[]): Configure httpx_mock fixture.",
)
6 changes: 2 additions & 4 deletions pytest_httpx/_httpx_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def __init__(
self,
*,
assert_all_responses_were_requested: bool = True,
assert_all_requests_were_expected: bool = False,
assert_all_requests_were_expected: bool = True,
non_mocked_hosts: Optional[list[str]] = None,
) -> None:
self.assert_all_responses_were_requested = assert_all_responses_were_requested
Expand All @@ -34,9 +34,7 @@ def __init__(

@classmethod
def from_marker(cls, marker: Mark) -> "HTTPXMockOptions":
"""Initialise from a marker so that the marker kwargs raise an error if
incorrect.
"""
"""Initialise from a marker so that the marker kwargs raise an error if incorrect."""
__tracebackhide__ = methodcaller("errisinstance", TypeError)
return cls(**marker.kwargs)

Expand Down
Loading

0 comments on commit 5cf03e3

Please sign in to comment.