diff --git a/CHANGELOG.md b/CHANGELOG.md index 5076319..aed2284 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 @@ -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. diff --git a/README.md b/README.md index 4d097c6..3a60d1f 100644 --- a/README.md +++ b/README.md @@ -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): @@ -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): ... ``` diff --git a/pytest_httpx/__init__.py b/pytest_httpx/__init__.py index 2837171..28f400d 100644 --- a/pytest_httpx/__init__.py +++ b/pytest_httpx/__init__.py @@ -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.", ) diff --git a/pytest_httpx/_httpx_mock.py b/pytest_httpx/_httpx_mock.py index 6c42b3b..33ac08b 100644 --- a/pytest_httpx/_httpx_mock.py +++ b/pytest_httpx/_httpx_mock.py @@ -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 @@ -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) diff --git a/tests/test_httpx_async.py b/tests/test_httpx_async.py index b3ef121..1d5d721 100644 --- a/tests/test_httpx_async.py +++ b/tests/test_httpx_async.py @@ -13,6 +13,7 @@ @pytest.mark.asyncio +@pytest.mark.httpx_mock(assert_all_requests_were_expected=False) async def test_without_response(httpx_mock: HTTPXMock) -> None: with pytest.raises(Exception) as exception_info: async with httpx.AsyncClient() as client: @@ -61,7 +62,9 @@ async def test_url_query_string_matching(httpx_mock: HTTPXMock) -> None: @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_url_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(url="https://test_url") @@ -76,7 +79,9 @@ async def test_url_not_matching(httpx_mock: HTTPXMock) -> None: @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_url_query_string_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(url="https://test_url?a=1&a=2") @@ -104,7 +109,9 @@ async def test_method_matching(httpx_mock: HTTPXMock) -> None: @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_method_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(method="get") @@ -1101,7 +1108,9 @@ async def test_multi_value_headers_matching(httpx_mock: HTTPXMock) -> None: @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_multi_value_headers_not_matching_single_value_issued( httpx_mock: HTTPXMock, ) -> None: @@ -1124,7 +1133,9 @@ async def test_multi_value_headers_not_matching_single_value_issued( @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_multi_value_headers_not_matching_multi_value_issued( httpx_mock: HTTPXMock, ) -> None: @@ -1147,7 +1158,9 @@ async def test_multi_value_headers_not_matching_multi_value_issued( @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_headers_matching_respect_case(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( match_headers={"user-agent": f"python-httpx/{httpx.__version__}"} @@ -1164,7 +1177,9 @@ async def test_headers_matching_respect_case(httpx_mock: HTTPXMock) -> None: @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_headers_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( match_headers={ @@ -1185,7 +1200,9 @@ async def test_headers_not_matching(httpx_mock: HTTPXMock) -> None: @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_url_not_matching_upper_case_headers_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1223,7 +1240,9 @@ async def test_proxy_matching(httpx_mock: HTTPXMock) -> None: @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_proxy_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(proxy_url="http://my_test_proxy") @@ -1238,7 +1257,9 @@ async def test_proxy_not_matching(httpx_mock: HTTPXMock) -> None: @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_proxy_not_existing(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(proxy_url="http://my_test_proxy") @@ -1317,7 +1338,9 @@ async def test_request_retrieval_proxy_matching(httpx_mock: HTTPXMock) -> None: @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_content_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(match_content=b"This is the body") @@ -1350,7 +1373,9 @@ async def test_json_partial_matching(httpx_mock: HTTPXMock) -> None: @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_json_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(match_json={"a": 1, "b": 2}) @@ -1365,7 +1390,9 @@ async def test_json_not_matching(httpx_mock: HTTPXMock) -> None: @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_headers_and_json_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( match_json={"a": 1, "b": 2}, @@ -1383,7 +1410,9 @@ async def test_headers_and_json_not_matching(httpx_mock: HTTPXMock) -> None: @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_match_json_invalid_json(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(match_json={"a": 1, "b": 2}) @@ -1410,7 +1439,9 @@ async def test_headers_and_content_matching(httpx_mock: HTTPXMock) -> None: @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_headers_not_matching_and_content_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( match_headers={ @@ -1431,7 +1462,9 @@ async def test_headers_not_matching_and_content_matching(httpx_mock: HTTPXMock) @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_headers_matching_and_content_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( match_headers={ @@ -1452,7 +1485,9 @@ async def test_headers_matching_and_content_not_matching(httpx_mock: HTTPXMock) @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_headers_and_content_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( match_headers={ @@ -1486,7 +1521,9 @@ async def test_url_and_headers_and_content_matching(httpx_mock: HTTPXMock) -> No @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_headers_not_matching_and_url_and_content_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1510,7 +1547,9 @@ async def test_headers_not_matching_and_url_and_content_matching( @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_url_and_headers_not_matching_and_content_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1534,7 +1573,9 @@ async def test_url_and_headers_not_matching_and_content_matching( @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_url_and_headers_matching_and_content_not_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1558,7 +1599,9 @@ async def test_url_and_headers_matching_and_content_not_matching( @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_headers_matching_and_url_and_content_not_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1582,7 +1625,9 @@ async def test_headers_matching_and_url_and_content_not_matching( @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_url_matching_and_headers_and_content_not_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1606,7 +1651,9 @@ async def test_url_matching_and_headers_and_content_not_matching( @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_url_and_headers_and_content_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( url="https://test_url2", @@ -1644,7 +1691,9 @@ async def test_method_and_url_and_headers_and_content_matching( @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_headers_not_matching_and_method_and_url_and_content_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1669,7 +1718,9 @@ async def test_headers_not_matching_and_method_and_url_and_content_matching( @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_url_and_headers_not_matching_and_method_and_content_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1694,7 +1745,9 @@ async def test_url_and_headers_not_matching_and_method_and_content_matching( @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_method_and_url_and_headers_matching_and_content_not_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1719,7 +1772,9 @@ async def test_method_and_url_and_headers_matching_and_content_not_matching( @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_method_and_headers_matching_and_url_and_content_not_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1744,7 +1799,9 @@ async def test_method_and_headers_matching_and_url_and_content_not_matching( @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_method_and_url_matching_and_headers_and_content_not_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1769,7 +1826,9 @@ async def test_method_and_url_matching_and_headers_and_content_not_matching( @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_method_matching_and_url_and_headers_and_content_not_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1794,7 +1853,9 @@ async def test_method_matching_and_url_and_headers_and_content_not_matching( @pytest.mark.asyncio -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) async def test_method_and_url_and_headers_and_content_not_matching( httpx_mock: HTTPXMock, ) -> None: diff --git a/tests/test_httpx_sync.py b/tests/test_httpx_sync.py index 3348cf4..3cbfb3f 100644 --- a/tests/test_httpx_sync.py +++ b/tests/test_httpx_sync.py @@ -9,6 +9,7 @@ from pytest_httpx import HTTPXMock +@pytest.mark.httpx_mock(assert_all_requests_were_expected=False) def test_without_response(httpx_mock: HTTPXMock) -> None: with pytest.raises(Exception) as exception_info: with httpx.Client() as client: @@ -53,7 +54,9 @@ def test_url_query_string_matching(httpx_mock: HTTPXMock) -> None: assert response.content == b"" -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_url_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(url="https://test_url") @@ -67,7 +70,9 @@ def test_url_not_matching(httpx_mock: HTTPXMock) -> None: ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_url_query_string_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(url="https://test_url?a=1&a=2") @@ -93,7 +98,9 @@ def test_method_matching(httpx_mock: HTTPXMock) -> None: assert response.content == b"" -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_method_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(method="get") @@ -134,7 +141,9 @@ def test_response_with_html_string_body(httpx_mock: HTTPXMock) -> None: assert response.text == "
test content" -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_url_not_matching_upper_case_headers_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( method="GET", @@ -872,7 +881,9 @@ def test_multi_value_headers_matching(httpx_mock: HTTPXMock) -> None: assert response.content == b"" -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_multi_value_headers_not_matching_single_value_issued( httpx_mock: HTTPXMock, ) -> None: @@ -894,7 +905,9 @@ def test_multi_value_headers_not_matching_single_value_issued( ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_multi_value_headers_not_matching_multi_value_issued( httpx_mock: HTTPXMock, ) -> None: @@ -916,7 +929,9 @@ def test_multi_value_headers_not_matching_multi_value_issued( ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_headers_matching_respect_case(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( match_headers={"user-agent": f"python-httpx/{httpx.__version__}"} @@ -932,7 +947,9 @@ def test_headers_matching_respect_case(httpx_mock: HTTPXMock) -> None: ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_headers_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( match_headers={ @@ -968,7 +985,9 @@ def test_proxy_matching(httpx_mock: HTTPXMock) -> None: assert response.read() == b"" -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_proxy_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(proxy_url="http://my_test_proxy") @@ -982,7 +1001,9 @@ def test_proxy_not_matching(httpx_mock: HTTPXMock) -> None: ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_proxy_not_existing(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(proxy_url="http://my_test_proxy") @@ -1052,7 +1073,9 @@ def test_request_retrieval_proxy_matching(httpx_mock: HTTPXMock) -> None: assert httpx_mock.get_request(proxy_url="http://my_test_proxy/") -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_content_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(match_content=b"This is the body") @@ -1092,7 +1115,9 @@ def test_json_partial_matching(httpx_mock: HTTPXMock) -> None: assert response.read() == b"" -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_json_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(match_json={"a": 1, "b": 2}) @@ -1106,7 +1131,9 @@ def test_json_not_matching(httpx_mock: HTTPXMock) -> None: ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_headers_and_json_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( match_json={"a": 1, "b": 2}, @@ -1123,7 +1150,9 @@ def test_headers_and_json_not_matching(httpx_mock: HTTPXMock) -> None: ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_match_json_invalid_json(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response(match_json={"a": 1, "b": 2}) @@ -1148,7 +1177,9 @@ def test_headers_and_content_matching(httpx_mock: HTTPXMock) -> None: assert response.content == b"" -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_headers_not_matching_and_content_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( match_headers={ @@ -1168,7 +1199,9 @@ def test_headers_not_matching_and_content_matching(httpx_mock: HTTPXMock) -> Non ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_headers_matching_and_content_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( match_headers={ @@ -1188,7 +1221,9 @@ def test_headers_matching_and_content_not_matching(httpx_mock: HTTPXMock) -> Non ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_headers_and_content_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( match_headers={ @@ -1220,7 +1255,9 @@ def test_url_and_headers_and_content_matching(httpx_mock: HTTPXMock) -> None: assert response.content == b"" -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_headers_not_matching_and_url_and_content_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1243,7 +1280,9 @@ def test_headers_not_matching_and_url_and_content_matching( ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_url_and_headers_not_matching_and_content_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1266,7 +1305,9 @@ def test_url_and_headers_not_matching_and_content_matching( ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_url_and_headers_matching_and_content_not_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1289,7 +1330,9 @@ def test_url_and_headers_matching_and_content_not_matching( ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_headers_matching_and_url_and_content_not_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1312,7 +1355,9 @@ def test_headers_matching_and_url_and_content_not_matching( ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_url_matching_and_headers_and_content_not_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1335,7 +1380,9 @@ def test_url_matching_and_headers_and_content_not_matching( ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_url_and_headers_and_content_not_matching(httpx_mock: HTTPXMock) -> None: httpx_mock.add_response( url="https://test_url2", @@ -1369,7 +1416,9 @@ def test_method_and_url_and_headers_and_content_matching(httpx_mock: HTTPXMock) assert response.content == b"" -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_headers_not_matching_and_method_and_url_and_content_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1393,7 +1442,9 @@ def test_headers_not_matching_and_method_and_url_and_content_matching( ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_url_and_headers_not_matching_and_method_and_content_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1417,7 +1468,9 @@ def test_url_and_headers_not_matching_and_method_and_content_matching( ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_method_and_url_and_headers_matching_and_content_not_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1441,7 +1494,9 @@ def test_method_and_url_and_headers_matching_and_content_not_matching( ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_method_and_headers_matching_and_url_and_content_not_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1465,7 +1520,9 @@ def test_method_and_headers_matching_and_url_and_content_not_matching( ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_method_and_url_matching_and_headers_and_content_not_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1489,7 +1546,9 @@ def test_method_and_url_matching_and_headers_and_content_not_matching( ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_method_matching_and_url_and_headers_and_content_not_matching( httpx_mock: HTTPXMock, ) -> None: @@ -1513,7 +1572,9 @@ def test_method_matching_and_url_and_headers_and_content_not_matching( ) -@pytest.mark.httpx_mock(assert_all_responses_were_requested=False) +@pytest.mark.httpx_mock( + assert_all_responses_were_requested=False, assert_all_requests_were_expected=False +) def test_method_and_url_and_headers_and_content_not_matching( httpx_mock: HTTPXMock, ) -> None: diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 791e3a0..2e4880d 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -107,8 +107,8 @@ def unused(*args, **kwargs): def test_httpx_mock_unexpected_request(testdir: Testdir) -> None: """ - Unexpected request should not fail test case if - assert_all_requests_were_expected option is set to False (default). + Unexpected request should fail test case if + assert_all_requests_were_expected option is set to True (default). """ testdir.makepyfile( """ @@ -123,20 +123,26 @@ def test_httpx_mock_unexpected_request(httpx_mock): """ ) result = testdir.runpytest() - result.assert_outcomes(passed=1) + result.assert_outcomes(errors=1, passed=1) + result.stdout.fnmatch_lines( + [ + "*AssertionError: The following requests were not expected:", + "*[