diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index bf73ffd..a80afbb 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -26,7 +26,7 @@ jobs:
pre-commit run --all-files
- name: Test
run: |
- pytest --cov-report=xml --junitxml=junit.xml -o junit_family=legacy
+ tox -- --cov-report=xml --junitxml=junit.xml -o junit_family=legacy
- name: Upload test results to Codecov
uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
with:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3584e33..3d7aceb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `match_params` is now handling `bool`, `int` and `float` values in addition to `str`. Only str values were previously expected.
- A meaningful error will now be returned when a callback that does not return an `httpx.Response` is called.
+### Added
+- Support for httpx2 is implemented. When both `httpx` and `httpx2` are installed, the `httpx_mock`
+ fixture now mocks both of them within the same test session.
+
+### Changed
+- `httpx` is not installed automatically anymore. You now have to require it explicitly through the `httpx` or `httpx2` extra.
+ Both extras can be installed at the same time to mock both libraries simultaneously.
+
### Removed
- python `3.10` is not supported anymore.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1192ab8..953c5d5 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -28,12 +28,13 @@ Title should be a small sentence describing the request.
1) Create a new branch based on `develop` branch.
2) Fetch all dependencies using [`pip`](https://pip.pypa.io/en/stable/).
```shell
- python -m pip install .[testing]
+ python -m pip install .[dev]
```
-3) Ensure tests are ok by running them using [`pytest`](https://doc.pytest.org/en/latest/index.html).
+3) Ensure tests are ok by running them using [`tox`](https://tox.wiki/en/4.65.4/index.html).
```shell
- pytest
+ tox
```
+ You can also run tests directly using [`pytest`](https://doc.pytest.org/en/latest/index.html).
4) Install [pre-commit](https://pre-commit.com) hook to ensure new code will follow guidelines.
```shell
python -m pip install pre-commit
diff --git a/README.md b/README.md
index 33ff065..180055e 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,23 @@
>
> However, current state can be considered as stable.
-Once installed, `httpx_mock` [`pytest`](https://docs.pytest.org/en/latest/) fixture will make sure every [`httpx`](https://www.python-httpx.org) request will be replied to with user provided responses ([unless some hosts are explicitly skipped](#do-not-mock-some-requests)).
+Since `pytest-httpx` supports both `httpx` and `httpx2`, it doesn't install any of them by itself,
+you have to pick which one (or both) you are using:
+
+```bash
+# For httpx.
+pip install pytest-httpx[httpx]
+# For httpx2.
+pip install pytest-httpx[httpx2]
+# For both.
+pip install pytest-httpx[httpx,httpx2]
+```
+
+Once installed, `httpx_mock` [`pytest`](https://docs.pytest.org/en/latest/) fixture will make sure every [`httpx`](https://www.python-httpx.org) or [`httpx2`](https://pydantic.dev/docs/httpx2/get-started/)
+request will be replied to with user provided responses ([unless some hosts are explicitly skipped](#do-not-mock-some-requests)).
+
+For brevity, both httpx and httpx2 will be further referred to as httpx. All the examples using httpx
+should stay intact when using httpx2.
- [Add responses](#add-responses)
- [JSON body](#add-json-response)
@@ -37,7 +53,7 @@ Once installed, `httpx_mock` [`pytest`](https://docs.pytest.org/en/latest/) fixt
## Add responses
-You can register responses for both sync and async [`HTTPX`](https://www.python-httpx.org) requests.
+You can register responses for both sync and async ([`HTTPX`](https://www.python-httpx.org)) requests.
```python
import pytest
diff --git a/pyproject.toml b/pyproject.toml
index 5018df2..6369409 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -39,7 +39,6 @@ classifiers = [
"Typing :: Typed",
]
dependencies = [
- "httpx==0.28.*",
"pytest==9.*",
]
dynamic = ["version"]
@@ -51,12 +50,18 @@ changelog = "https://github.com/Colin-b/pytest_httpx/blob/master/CHANGELOG.md"
issues = "https://github.com/Colin-b/pytest_httpx/issues"
[project.optional-dependencies]
+httpx = ["httpx==0.28.*"]
+httpx2 = ["httpx2==2.*"]
testing = [
# Used to check coverage
"pytest-cov==7.*",
# Used to run async tests
"pytest-asyncio==1.*",
]
+dev = [
+ "pytest-httpx[testing,httpx,httpx2]",
+ "tox==4.*"
+]
[project.entry-points.pytest11]
pytest_httpx = "pytest_httpx"
diff --git a/pytest_httpx/__init__.py b/pytest_httpx/__init__.py
index 8460cb0..95ce3cc 100644
--- a/pytest_httpx/__init__.py
+++ b/pytest_httpx/__init__.py
@@ -1,67 +1,78 @@
from collections.abc import Generator
from operator import methodcaller
-import httpx
import pytest
from pytest import Config, FixtureRequest, MonkeyPatch
+from pytest_httpx._httpx_compat import HTTPXBackend, get_backends
from pytest_httpx._httpx_internals import IteratorStream
from pytest_httpx._httpx_mock import HTTPXMock
from pytest_httpx._options import _HTTPXMockOptions
from pytest_httpx.version import __version__
__all__ = (
+ "HTTPXBackend",
"HTTPXMock",
"IteratorStream",
"__version__",
+ "get_backends",
)
-@pytest.fixture
-def httpx_mock(
+def _mock_backend(
monkeypatch: MonkeyPatch,
- request: FixtureRequest,
-) -> Generator[HTTPXMock, None, None]:
- httpx_mock_markers: dict = {}
- for marker in request.node.iter_markers("httpx_mock"):
- httpx_mock_markers = marker.kwargs | httpx_mock_markers
- __tracebackhide__ = methodcaller("errisinstance", TypeError)
- options = _HTTPXMockOptions(**httpx_mock_markers)
-
- mock = HTTPXMock(options)
-
+ options: _HTTPXMockOptions,
+ mock: HTTPXMock,
+ backend: HTTPXBackend,
+) -> None:
# Mock synchronous requests
- real_handle_request = httpx.HTTPTransport.handle_request
+ real_handle_request = backend.httpx.HTTPTransport.handle_request
- def mocked_handle_request(
- transport: httpx.HTTPTransport, request: httpx.Request
- ) -> httpx.Response:
+ def mocked_handle_request(transport, request): # type: ignore[no-untyped-def]
if options.should_mock(request):
- return mock._handle_request(transport, request)
+ return mock._handle_request(backend, transport, request)
return real_handle_request(transport, request)
monkeypatch.setattr(
- httpx.HTTPTransport,
+ backend.httpx.HTTPTransport,
"handle_request",
mocked_handle_request,
)
# Mock asynchronous requests
- real_handle_async_request = httpx.AsyncHTTPTransport.handle_async_request
+ real_handle_async_request = backend.httpx.AsyncHTTPTransport.handle_async_request
- async def mocked_handle_async_request(
- transport: httpx.AsyncHTTPTransport, request: httpx.Request
- ) -> httpx.Response:
+ async def mocked_handle_async_request(transport, request): # type: ignore[no-untyped-def]
if options.should_mock(request):
- return await mock._handle_async_request(transport, request)
+ return await mock._handle_async_request(backend, transport, request)
return await real_handle_async_request(transport, request)
monkeypatch.setattr(
- httpx.AsyncHTTPTransport,
+ backend.httpx.AsyncHTTPTransport,
"handle_async_request",
mocked_handle_async_request,
)
+
+@pytest.fixture
+def httpx_mock(
+ monkeypatch: MonkeyPatch,
+ request: FixtureRequest,
+) -> Generator[HTTPXMock, None, None]:
+ httpx_mock_markers: dict = {}
+
+ for marker in request.node.iter_markers("httpx_mock"):
+ httpx_mock_markers = marker.kwargs | httpx_mock_markers
+
+ __tracebackhide__ = methodcaller("errisinstance", TypeError)
+ options = _HTTPXMockOptions(**httpx_mock_markers)
+
+ mock = HTTPXMock(options)
+
+ # Mock sync and async transports of every installed httpx backend.
+ for backend in get_backends():
+ _mock_backend(monkeypatch, options, mock, backend)
+
yield mock
try:
mock._assert_options()
diff --git a/pytest_httpx/_httpx_compat.py b/pytest_httpx/_httpx_compat.py
new file mode 100644
index 0000000..bb0038f
--- /dev/null
+++ b/pytest_httpx/_httpx_compat.py
@@ -0,0 +1,65 @@
+from dataclasses import dataclass
+from functools import cache
+from types import ModuleType
+from typing import TYPE_CHECKING, Literal
+
+
+@dataclass(frozen=True)
+class HTTPXBackend:
+ name: Literal["httpx", "httpx2"]
+ httpx: ModuleType
+ httpcore: ModuleType
+
+
+@cache
+def get_backends() -> list[HTTPXBackend]:
+ """Return every httpx backend found in the environment."""
+
+ backends = []
+
+ try:
+ import httpcore2 as httpcore2_ # pragma: no cover
+ import httpx2 as httpx2_ # pragma: no cover
+ except ModuleNotFoundError: # pragma: no cover
+ pass
+ else:
+ backends.append(HTTPXBackend("httpx2", httpx2_, httpcore2_)) # pragma: no cover
+
+ try:
+ import httpcore as httpcore_ # pragma: no cover
+ import httpx as httpx_ # pragma: no cover
+ except ModuleNotFoundError: # pragma: no cover
+ pass
+ else:
+ backends.append(HTTPXBackend("httpx", httpx_, httpcore_)) # pragma: no cover
+
+ if not backends: # pragma: no cover
+ raise RuntimeError(
+ "pytest-httpx requires either httpx or httpx2 to be installed.\n"
+ "They are now optional dependencies, install the matching extra with:\n"
+ " $ pip install pytest-httpx[httpx2]\n"
+ "or:\n"
+ " $ pip install pytest-httpx[httpx]\n"
+ )
+
+ return backends
+
+
+_BACKEND_ATTRIBUTE = "__pytest_httpx_backend"
+
+
+def set_backend(request: "httpx.Request", backend: HTTPXBackend) -> None:
+ # Store the intercepting backend on the request so that backend-agnostic
+ # callbacks (e.g. the one built by `add_response`) can build a response
+ # with the matching library.
+ setattr(request, _BACKEND_ATTRIBUTE, backend)
+
+
+def get_backend(request: "httpx.Request") -> HTTPXBackend:
+ return getattr(request, _BACKEND_ATTRIBUTE)
+
+
+if TYPE_CHECKING:
+ import httpcore # noqa: F401
+ import httpx
+ import httpx2 # noqa: F401
diff --git a/pytest_httpx/_httpx_internals.py b/pytest_httpx/_httpx_internals.py
index 11fe1c0..c0c953a 100644
--- a/pytest_httpx/_httpx_internals.py
+++ b/pytest_httpx/_httpx_internals.py
@@ -1,42 +1,54 @@
import base64
from collections.abc import AsyncIterator, Iterable, Iterator, Sequence
-from typing import TypeAlias
+from typing import TYPE_CHECKING, TypeAlias, Union
-import httpcore
-import httpx
+from pytest_httpx._httpx_compat import HTTPXBackend, get_backends
-# TODO Get rid of this internal import
-from httpx._content import AsyncIteratorByteStream, IteratorByteStream
+if TYPE_CHECKING:
+ from pytest_httpx._httpx_compat import httpcore, httpx, httpx2
# Those types are internally defined within httpx._types
-HeaderTypes: TypeAlias = (
- httpx.Headers
- | dict[str, str]
- | dict[bytes, bytes]
- | Sequence[tuple[str, str]]
- | Sequence[tuple[bytes, bytes]]
-)
-PrimitiveData: TypeAlias = str | int | float | bool | None
+HeaderTypes: TypeAlias = Union[
+ "httpx.Headers",
+ "httpx2.Headers",
+ dict[str, str],
+ dict[bytes, bytes],
+ Sequence[tuple[str, str]],
+ Sequence[tuple[bytes, bytes]],
+]
+PrimitiveData: TypeAlias = str | int | float | bool
-class IteratorStream(AsyncIteratorByteStream, IteratorByteStream):
+def _iterator_stream_bases() -> list[type]:
+ bases: list[type] = []
+
+ for backend in get_backends():
+ bases.append(backend.httpx.SyncByteStream)
+ bases.append(backend.httpx.AsyncByteStream)
+
+ return bases
+
+
+class IteratorStream(*_iterator_stream_bases()): # type: ignore[misc]
def __init__(self, stream: Iterable[bytes]):
- class Stream:
- def __iter__(self) -> Iterator[bytes]:
- yield from stream
+ self._stream = stream
- async def __aiter__(self) -> AsyncIterator[bytes]:
- for chunk in stream:
- yield chunk
+ def __iter__(self) -> Iterator[bytes]:
+ yield from self._stream
- AsyncIteratorByteStream.__init__(self, stream=Stream())
- IteratorByteStream.__init__(self, stream=Stream())
+ async def __aiter__(self) -> AsyncIterator[bytes]:
+ for chunk in self._stream:
+ yield chunk
-def _to_httpx_url(url: httpcore.URL, headers: list[tuple[bytes, bytes]]) -> httpx.URL:
+def _to_httpx_url(
+ backend: HTTPXBackend,
+ url: "httpcore.URL",
+ headers: list[tuple[bytes, bytes]],
+) -> "httpx.URL":
for name, value in headers:
if b"Proxy-Authorization" == name:
- return httpx.URL(
+ return backend.httpx.URL(
scheme=url.scheme.decode(),
host=url.host.decode(),
port=url.port,
@@ -44,7 +56,7 @@ def _to_httpx_url(url: httpcore.URL, headers: list[tuple[bytes, bytes]]) -> http
userinfo=base64.b64decode(value[6:]),
)
- return httpx.URL(
+ return backend.httpx.URL(
scheme=url.scheme.decode(),
host=url.host.decode(),
port=url.port,
@@ -53,10 +65,12 @@ def _to_httpx_url(url: httpcore.URL, headers: list[tuple[bytes, bytes]]) -> http
def _proxy_url(
- real_transport: httpx.HTTPTransport | httpx.AsyncHTTPTransport,
-) -> httpx.URL | None:
+ backend: HTTPXBackend,
+ real_transport: "httpx.HTTPTransport | httpx.AsyncHTTPTransport",
+) -> "httpx.URL | None":
if isinstance(
- real_pool := real_transport._pool, (httpcore.HTTPProxy, httpcore.AsyncHTTPProxy)
+ real_pool := real_transport._pool,
+ (backend.httpcore.HTTPProxy, backend.httpcore.AsyncHTTPProxy),
):
- return _to_httpx_url(real_pool._proxy_url, real_pool._proxy_headers)
+ return _to_httpx_url(backend, real_pool._proxy_url, real_pool._proxy_headers)
return None
diff --git a/pytest_httpx/_httpx_mock.py b/pytest_httpx/_httpx_mock.py
index 5b7468d..58c58c1 100644
--- a/pytest_httpx/_httpx_mock.py
+++ b/pytest_httpx/_httpx_mock.py
@@ -1,15 +1,29 @@
import copy
import inspect
from collections.abc import Awaitable, Callable
-from typing import Any
-
-import httpx
+from typing import TYPE_CHECKING, Any, TypeAlias
from pytest_httpx import _httpx_internals
+from pytest_httpx._httpx_compat import HTTPXBackend, get_backend, set_backend
from pytest_httpx._options import _HTTPXMockOptions
from pytest_httpx._pretty_print import RequestDescription
from pytest_httpx._request_matcher import _RequestMatcher
+if TYPE_CHECKING:
+ from pytest_httpx._httpx_compat import httpx, httpx2
+
+
+Callback: TypeAlias = (
+ Callable[
+ ["httpx.Request"],
+ "httpx.Response | None | Awaitable[httpx.Response | None]",
+ ]
+ | Callable[
+ ["httpx2.Request"],
+ "httpx2.Response | None | Awaitable[httpx2.Response | None]",
+ ]
+)
+
class HTTPXMock:
"""
@@ -25,10 +39,7 @@ def __init__(self, options: _HTTPXMockOptions) -> None:
self._callbacks: list[
tuple[
_RequestMatcher,
- Callable[
- [httpx.Request],
- httpx.Response | None | Awaitable[httpx.Response | None],
- ],
+ Callback,
]
] = []
self._requests_not_matched: list[httpx.Request] = []
@@ -74,8 +85,11 @@ def add_response(
json = copy.deepcopy(json) if json is not None else None
- def response_callback(request: httpx.Request) -> httpx.Response:
- return httpx.Response(
+ def response_callback(request: "httpx.Request") -> "httpx.Response":
+ # Build the response with the backend that intercepted the request
+ # so that its type matches the client.
+ backend = get_backend(request)
+ return backend.httpx.Response(
status_code=status_code,
extensions={"http_version": http_version.encode("ascii")},
headers=headers,
@@ -90,10 +104,7 @@ def response_callback(request: httpx.Request) -> httpx.Response:
def add_callback(
self,
- callback: Callable[
- [httpx.Request],
- httpx.Response | None | Awaitable[httpx.Response | None],
- ],
+ callback: Callback,
**matchers: Any,
) -> None:
"""
@@ -139,8 +150,10 @@ def add_exception(self, exception: BaseException, **matchers: Any) -> None:
:param is_reusable: True will allow re-using this exception response even if it already matched, False prevent re-using it. Must be a boolean. Default to the can_send_already_matched_responses option value (itself defaulting to False).
"""
- def exception_callback(request: httpx.Request) -> None:
- if isinstance(exception, httpx.RequestError):
+ def exception_callback(request: "httpx.Request") -> None:
+ backend = get_backend(request)
+
+ if isinstance(exception, backend.httpx.RequestError):
exception.request = request
raise exception
@@ -148,9 +161,14 @@ def exception_callback(request: httpx.Request) -> None:
def _handle_request(
self,
- real_transport: httpx.HTTPTransport,
- request: httpx.Request,
- ) -> httpx.Response:
+ backend: HTTPXBackend,
+ real_transport: "httpx.HTTPTransport",
+ request: "httpx.Request",
+ ) -> "httpx.Response":
+ # Save the backend that intercepted this request so that callbacks
+ # use the matching library.
+ set_backend(request, backend)
+
# Store the content in request for future matching
request.read()
self._requests.append((real_transport, request))
@@ -159,7 +177,7 @@ def _handle_request(
if callback:
response = callback(request)
- if isinstance(response, httpx.Response):
+ if isinstance(response, backend.httpx.Response):
return _unread(response)
raise self._request_not_matched(
@@ -175,9 +193,14 @@ def _handle_request(
async def _handle_async_request(
self,
- real_transport: httpx.AsyncHTTPTransport,
- request: httpx.Request,
- ) -> httpx.Response:
+ backend: HTTPXBackend,
+ real_transport: "httpx.AsyncHTTPTransport",
+ request: "httpx.Request",
+ ) -> "httpx.Response":
+ # Save the backend that intercepted this request so that callbacks
+ # use the matching library.
+ set_backend(request, backend)
+
# Store the content in request for future matching
await request.aread()
self._requests.append((real_transport, request))
@@ -189,7 +212,7 @@ async def _handle_async_request(
if inspect.isawaitable(response):
response = await response
- if isinstance(response, httpx.Response):
+ if isinstance(response, backend.httpx.Response):
return _unread(response)
raise self._request_not_matched(
@@ -204,22 +227,24 @@ async def _handle_async_request(
)
def _request_not_matched(
- self, request: httpx.Request, message: str
- ) -> httpx.TimeoutException:
+ self, request: "httpx.Request", message: str
+ ) -> "httpx.TimeoutException":
+ backend = get_backend(request)
self._requests_not_matched.append(request)
- return httpx.TimeoutException(message, request=request)
+ return backend.httpx.TimeoutException(message, request=request)
def _explain_that_callback_must_return_a_response(
self,
- real_transport: httpx.BaseTransport | httpx.AsyncBaseTransport,
- request: httpx.Request,
+ real_transport: "httpx.HTTPTransport | httpx.AsyncHTTPTransport",
+ request: "httpx.Request",
) -> str:
- return f"Callback registered for {RequestDescription(real_transport, request, [])} MUST return httpx.Response"
+ backend = get_backend(request)
+ return f"Callback registered for {RequestDescription(real_transport, request, [])} MUST return {backend.name}.Response"
def _explain_that_no_response_was_found(
self,
- real_transport: httpx.BaseTransport | httpx.AsyncBaseTransport,
- request: httpx.Request,
+ real_transport: "httpx.HTTPTransport | httpx.AsyncHTTPTransport",
+ request: "httpx.Request",
) -> str:
matchers = [matcher for matcher, _ in self._callbacks]
@@ -247,14 +272,9 @@ def _explain_that_no_response_was_found(
def _get_callback(
self,
- real_transport: httpx.HTTPTransport | httpx.AsyncHTTPTransport,
- request: httpx.Request,
- ) -> (
- Callable[
- [httpx.Request], httpx.Response | None | Awaitable[httpx.Response | None]
- ]
- | None
- ):
+ real_transport: "httpx.HTTPTransport | httpx.AsyncHTTPTransport",
+ request: "httpx.Request",
+ ) -> Callback | None:
callbacks = [
(matcher, callback)
for matcher, callback in self._callbacks
@@ -280,7 +300,7 @@ def _get_callback(
# All callbacks have already been matched and last registered cannot be reused
return None
- def get_requests(self, **matchers: Any) -> list[httpx.Request]:
+ def get_requests(self, **matchers: Any) -> list["httpx.Request | httpx2.Request"]:
"""
Return all requests sent that match (empty list if no requests were matched).
@@ -304,7 +324,7 @@ def get_requests(self, **matchers: Any) -> list[httpx.Request]:
if matcher.match(real_transport, request)
]
- def get_request(self, **matchers: Any) -> httpx.Request | None:
+ def get_request(self, **matchers: Any) -> "httpx.Request | httpx2.Request | None":
"""
Return the single request that match (or None).
@@ -363,7 +383,7 @@ def _assert_options(self) -> None:
)
-def _unread(response: httpx.Response) -> httpx.Response:
+def _unread(response: "httpx.Response") -> "httpx.Response":
# Allow to read the response on client side
response.is_stream_consumed = False
response.is_closed = False
diff --git a/pytest_httpx/_options.py b/pytest_httpx/_options.py
index 7f13ee5..b623cba 100644
--- a/pytest_httpx/_options.py
+++ b/pytest_httpx/_options.py
@@ -1,6 +1,8 @@
from collections.abc import Callable
+from typing import TYPE_CHECKING
-import httpx
+if TYPE_CHECKING:
+ from pytest_httpx._httpx_compat import httpx, httpx2
class _HTTPXMockOptions:
@@ -10,7 +12,9 @@ def __init__(
assert_all_responses_were_requested: bool = True,
assert_all_requests_were_expected: bool = True,
can_send_already_matched_responses: bool = False,
- should_mock: Callable[[httpx.Request], bool] = lambda request: True,
+ should_mock: Callable[
+ ["httpx.Request | httpx2.Request"], bool
+ ] = lambda request: True,
) -> None:
self.assert_all_responses_were_requested = assert_all_responses_were_requested
self.assert_all_requests_were_expected = assert_all_requests_were_expected
diff --git a/pytest_httpx/_pretty_print.py b/pytest_httpx/_pretty_print.py
index 60af8cd..c1b0c6e 100644
--- a/pytest_httpx/_pretty_print.py
+++ b/pytest_httpx/_pretty_print.py
@@ -1,16 +1,21 @@
-import httpx
+from typing import TYPE_CHECKING
+from pytest_httpx._httpx_compat import get_backend
from pytest_httpx._httpx_internals import _proxy_url
from pytest_httpx._request_matcher import _RequestMatcher
+if TYPE_CHECKING:
+ from pytest_httpx._httpx_compat import httpx
+
class RequestDescription:
def __init__(
self,
- real_transport: httpx.BaseTransport | httpx.AsyncBaseTransport,
- request: httpx.Request,
+ real_transport: "httpx.HTTPTransport | httpx.AsyncHTTPTransport",
+ request: "httpx.Request",
matchers: list[_RequestMatcher],
):
+ self.backend = get_backend(request)
self.real_transport = real_transport
self.request = request
@@ -58,7 +63,7 @@ def extra_request_description(self) -> str:
extra_description.append(f"{self.request.read()} body")
if self.expect_proxy:
- proxy_url = _proxy_url(self.real_transport)
+ proxy_url = _proxy_url(self.backend, self.real_transport)
extra_description.append(f"{proxy_url if proxy_url else 'no'} proxy URL")
if self.expected_extensions:
diff --git a/pytest_httpx/_request_matcher.py b/pytest_httpx/_request_matcher.py
index b73a01f..1ac4c80 100644
--- a/pytest_httpx/_request_matcher.py
+++ b/pytest_httpx/_request_matcher.py
@@ -1,16 +1,17 @@
import json
import re
from collections.abc import Sequence
-from re import Pattern
-from typing import Any
+from typing import TYPE_CHECKING, Any
from unittest.mock import ANY
-import httpx
-from httpx import QueryParams
-
+from pytest_httpx import get_backends
+from pytest_httpx._httpx_compat import HTTPXBackend, get_backend
from pytest_httpx._httpx_internals import PrimitiveData, _proxy_url
from pytest_httpx._options import _HTTPXMockOptions
+if TYPE_CHECKING:
+ from pytest_httpx._httpx_compat import httpx, httpx2
+
def convert_back_mock_any(original: dict, new: dict) -> None:
"""
@@ -30,17 +31,23 @@ def convert_back_mock_any(original: dict, new: dict) -> None:
def _url_match(
- url_to_match: Pattern[str] | httpx.URL,
- received: httpx.URL,
+ backend: HTTPXBackend,
+ url_to_match: "re.Pattern[str] | httpx.URL",
+ received: "httpx.URL",
params: dict[str, PrimitiveData | Sequence[PrimitiveData]] | None,
) -> bool:
if isinstance(url_to_match, re.Pattern):
return url_to_match.match(str(received)) is not None
+ # The expected URL may have been built with a different backend than the one
+ # that received the request, so normalize it to the request's backend before
+ # comparing.
+ url_to_match = backend.httpx.URL(str(url_to_match))
+
# Compare query parameters apart as order of parameters should not matter
received_params = to_params_dict(received.params)
expected_params = to_params_dict(
- url_to_match.params if params is None else QueryParams(params)
+ url_to_match.params if params is None else backend.httpx.QueryParams(params)
)
if params:
convert_back_mock_any(params, expected_params)
@@ -52,7 +59,9 @@ def _url_match(
return (received_params == expected_params) and (url == received_url)
-def to_params_dict(params: QueryParams) -> dict[str, str | list[str]]:
+def to_params_dict(
+ params: "httpx.QueryParams",
+) -> dict[str, str | list[str]]:
"""Convert query parameters to a dict where the value is a string if the parameter has a single value and a list of string otherwise."""
d = {}
for key in params:
@@ -65,9 +74,9 @@ class _RequestMatcher:
def __init__(
self,
options: _HTTPXMockOptions,
- url: str | Pattern[str] | httpx.URL | None = None,
+ url: "str | re.Pattern[str] | httpx.URL | httpx2.URL | None" = None,
method: str | None = None,
- proxy_url: str | Pattern[str] | httpx.URL | None = None,
+ proxy_url: "str | re.Pattern[str] | httpx.URL | httpx2.URL | None" = None,
match_headers: dict[str, Any] | None = None,
match_content: bytes | None = None,
match_json: Any | None = None,
@@ -80,7 +89,7 @@ def __init__(
):
self._options = options
self.nb_calls = 0
- self.url = httpx.URL(url) if url and isinstance(url, str) else url
+ self.url = url
self.method = method.upper() if method else method
self.headers = match_headers
self.content = match_content
@@ -88,11 +97,7 @@ def __init__(
self.data = match_data
self.files = match_files
self.params = match_params
- self.proxy_url = (
- httpx.URL(proxy_url)
- if proxy_url and isinstance(proxy_url, str)
- else proxy_url
- )
+ self.proxy_url = proxy_url
self.extensions = match_extensions
self.is_optional = (
not options.assert_all_responses_were_requested
@@ -144,11 +149,14 @@ def _is_matching_body_more_than_one_way(self) -> bool:
return sum(matching_ways) > 1
def _is_matching_params_more_than_one_way(self) -> bool:
- url_has_params = (
- bool(self.url.params)
- if (self.url and isinstance(self.url, httpx.URL))
- else False
- )
+ if not self.url or isinstance(self.url, re.Pattern):
+ return False
+
+ [any_backend, *_] = get_backends()
+ # It doesn't matter which backend to use, both
+ # httpx and httpx2 has the same URL params parsing logic.
+ url_has_params = bool(any_backend.httpx.URL(str(self.url)).params)
+
matching_ways = [
self.params is not None,
url_has_params,
@@ -157,31 +165,32 @@ def _is_matching_params_more_than_one_way(self) -> bool:
def match(
self,
- real_transport: httpx.HTTPTransport | httpx.AsyncHTTPTransport,
- request: httpx.Request,
+ real_transport: "httpx.HTTPTransport | httpx.AsyncHTTPTransport",
+ request: "httpx.Request",
) -> bool:
+ backend = get_backend(request)
return (
- self._url_match(request)
+ self._url_match(backend, request)
and self._method_match(request)
and self._headers_match(request)
- and self._content_match(request)
- and self._proxy_match(real_transport)
+ and self._content_match(backend, request)
+ and self._proxy_match(backend, real_transport)
and self._extensions_match(request)
)
- def _url_match(self, request: httpx.Request) -> bool:
+ def _url_match(self, backend: HTTPXBackend, request: "httpx.Request") -> bool:
if not self.url:
return True
- return _url_match(self.url, request.url, self.params)
+ return _url_match(backend, self.url, request.url, self.params)
- def _method_match(self, request: httpx.Request) -> bool:
+ def _method_match(self, request: "httpx.Request") -> bool:
if not self.method:
return True
return request.method == self.method
- def _headers_match(self, request: httpx.Request) -> bool:
+ def _headers_match(self, request: "httpx.Request") -> bool:
if not self.headers:
return True
@@ -200,7 +209,7 @@ def _headers_match(self, request: httpx.Request) -> bool:
for header_name, header_value in self.headers.items()
)
- def _content_match(self, request: httpx.Request) -> bool:
+ def _content_match(self, backend: HTTPXBackend, request: "httpx.Request") -> bool:
if self.content is not None:
return request.content == self.content
@@ -219,7 +228,7 @@ def _content_match(self, request: httpx.Request) -> bool:
# Ensure we re-use the same boundary for comparison
boundary = boundary_matched.group(1)
# Prevent internal httpx changes from impacting users not matching on files
- from httpx._multipart import MultipartStream
+ MultipartStream = backend.httpx._multipart.MultipartStream
multipart_content = b"".join(
MultipartStream(self.data or {}, self.files, boundary)
@@ -229,17 +238,19 @@ def _content_match(self, request: httpx.Request) -> bool:
return True
def _proxy_match(
- self, real_transport: httpx.HTTPTransport | httpx.AsyncHTTPTransport
+ self,
+ backend: HTTPXBackend,
+ real_transport: "httpx.HTTPTransport | httpx.AsyncHTTPTransport",
) -> bool:
if not self.proxy_url:
return True
- if real_proxy_url := _proxy_url(real_transport):
- return _url_match(self.proxy_url, real_proxy_url, params=None)
+ if real_proxy_url := _proxy_url(backend, real_transport):
+ return _url_match(backend, self.proxy_url, real_proxy_url, params=None)
return False
- def _extensions_match(self, request: httpx.Request) -> bool:
+ def _extensions_match(self, request: "httpx.Request") -> bool:
if not self.extensions:
return True
diff --git a/tests/conftest.py b/tests/conftest.py
index 4c58045..b188679 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,2 +1,23 @@
# see https://docs.pytest.org/en/documentation-restructure/how-to/writing_plugins.html#testing-plugins
+import pytest
+
+from pytest_httpx import HTTPXBackend, get_backends
+
pytest_plugins = ["pytester"]
+
+
+@pytest.fixture(params=get_backends(), ids=lambda b: b.name)
+def backend(request: pytest.FixtureRequest) -> HTTPXBackend:
+ return request.param
+
+
+@pytest.fixture
+def plugin_tests_conftest(testdir: pytest.Testdir) -> None:
+ testdir.makeconftest("""
+ import pytest
+ from pytest_httpx import get_backends
+
+ @pytest.fixture(params=get_backends(), ids=lambda b: b.name)
+ def backend(request):
+ return request.param
+ """)
diff --git a/tests/test_backends.py b/tests/test_backends.py
new file mode 100644
index 0000000..4364b7a
--- /dev/null
+++ b/tests/test_backends.py
@@ -0,0 +1,180 @@
+import pytest
+
+try:
+ import httpx
+ import httpx2
+except ModuleNotFoundError:
+ # If one of the modules isn't installed, there's no sense running these tests.
+ pytest.skip(
+ allow_module_level=True, reason="One of http/httpx2 modules is missing."
+ )
+
+from pytest_httpx import HTTPXMock, get_backends
+
+
+def test_two_backends_two_names() -> None:
+ backends = get_backends()
+ names = {backend.name for backend in backends}
+
+ assert names == {"httpx", "httpx2"}
+
+
+def test_two_backends_are_different() -> None:
+ backends = get_backends()
+ modules = {id(backend.httpx) for backend in backends}
+
+ assert len(modules) == 2
+
+
+def test_single_add_response_mocks_both_backends(httpx_mock: HTTPXMock) -> None:
+ httpx_mock.add_response(text="hello", is_reusable=True)
+
+ with httpx.Client() as client:
+ httpx_response = client.get("https://test_url")
+
+ with httpx2.Client() as client:
+ httpx2_response = client.get("https://test_url")
+
+ assert httpx_response.text == "hello"
+ assert httpx2_response.text == "hello"
+
+
+@pytest.mark.asyncio
+async def test_single_add_response_mocks_both_async_backends(
+ httpx_mock: HTTPXMock,
+) -> None:
+ httpx_mock.add_response(text="async hello", is_reusable=True)
+
+ async with httpx.AsyncClient() as client:
+ httpx_response = await client.get("https://test_url")
+
+ async with httpx2.AsyncClient() as client:
+ httpx2_response = await client.get("https://test_url")
+
+ assert httpx_response.text == "async hello"
+ assert httpx2_response.text == "async hello"
+
+
+def test_response_type_matches_backend(httpx_mock: HTTPXMock) -> None:
+ httpx_mock.add_response(is_reusable=True)
+
+ with httpx.Client() as client:
+ httpx_response = client.get("https://test_url")
+
+ with httpx2.Client() as client:
+ httpx2_response = client.get("https://test_url")
+
+ assert isinstance(httpx_response, httpx.Response)
+ assert not isinstance(httpx_response, httpx2.Response)
+
+ assert isinstance(httpx2_response, httpx2.Response)
+ assert not isinstance(httpx2_response, httpx.Response)
+
+
+def test_requests_from_both_backends_are_retrieved(
+ httpx_mock: HTTPXMock,
+) -> None:
+ httpx_mock.add_response(is_reusable=True)
+
+ with httpx.Client() as client:
+ client.get("https://httpx_url")
+
+ with httpx2.Client() as client:
+ client.options("https://httpx2_url")
+
+ all_requests = httpx_mock.get_requests()
+
+ assert len(all_requests) == 2
+
+ httpx_request = httpx_mock.get_request(url="https://httpx_url")
+
+ assert httpx_request
+ assert httpx_request.method == "GET"
+
+ httpx2_request = httpx_mock.get_request(url="https://httpx2_url")
+
+ assert httpx2_request
+ assert httpx2_request.method == "OPTIONS"
+
+
+def test_responses_matched_in_registration_order(
+ httpx_mock: HTTPXMock,
+) -> None:
+ httpx_mock.add_response(text="first")
+ httpx_mock.add_response(text="second")
+
+ with httpx.Client() as client:
+ first_response = client.get("https://test_url")
+
+ with httpx2.Client() as client:
+ second_response = client.get("https://test_url")
+
+ assert first_response.text == "first"
+ assert second_response.text == "second"
+
+
+def test_add_exception_raises_matching_backend_error(httpx_mock: HTTPXMock) -> None:
+ httpx_mock.add_exception(
+ httpx.ReadTimeout("HTTPX timeout"), url="https://httpx_url"
+ )
+ httpx_mock.add_exception(
+ httpx2.ReadTimeout("HTTPX2 timeout"), url="https://httpx2_url"
+ )
+
+ with httpx.Client() as client, pytest.raises(httpx.ReadTimeout) as httpx_exc:
+ client.get("https://httpx_url")
+
+ assert str(httpx_exc.value) == "HTTPX timeout"
+ assert httpx_exc.value.request.url == httpx.URL("https://httpx_url")
+
+ with httpx2.Client() as client, pytest.raises(httpx2.ReadTimeout) as httpx2_exc:
+ client.get("https://httpx2_url")
+
+ assert str(httpx2_exc.value) == "HTTPX2 timeout"
+ assert httpx2_exc.value.request.url == httpx2.URL("https://httpx2_url")
+
+
+seen_request_modules: set[str] = set()
+
+
+def _should_mock(request: httpx.Request | httpx2.Request) -> bool:
+ # Record the module of the request object so the test below could check them.
+ match type(request):
+ case httpx.Request:
+ seen_request_modules.add("httpx")
+ case httpx2.Request:
+ seen_request_modules.add("httpx2")
+
+ return True
+
+
+@pytest.mark.httpx_mock(should_mock=_should_mock)
+def test_should_mock_used_by_both_backends(httpx_mock: HTTPXMock) -> None:
+ seen_request_modules.clear()
+ httpx_mock.add_response(is_reusable=True)
+
+ with httpx.Client() as client:
+ client.get("https://test_url")
+
+ with httpx2.Client() as client:
+ client.get("https://test_url")
+
+ assert set(seen_request_modules) == {"httpx", "httpx2"}
+
+
+def test_conflicting_params_backend_agnostic(httpx_mock: HTTPXMock) -> None:
+ with pytest.raises(ValueError) as exc_httpx:
+ httpx_mock.add_response(
+ url=httpx.URL("https://test_url?a=1"), match_params={"a": "1"}
+ )
+
+ with pytest.raises(ValueError) as exc_httpx2:
+ httpx_mock.add_response(
+ url=httpx2.URL("https://test_url?a=1"), match_params={"a": "1"}
+ )
+
+ assert (
+ str(exc_httpx.value)
+ == str(exc_httpx2.value)
+ == "Provided URL must not contain any query parameter when match_params is used."
+ )
diff --git a/tests/test_httpx_async.py b/tests/test_httpx_async.py
index f045bd8..08afe16 100644
--- a/tests/test_httpx_async.py
+++ b/tests/test_httpx_async.py
@@ -4,22 +4,27 @@
import re
import time
from collections.abc import AsyncIterable
-from typing import Any
+from typing import TYPE_CHECKING, Any
from unittest.mock import ANY
-import httpx
import pytest
from pytest import Testdir
import pytest_httpx
-from pytest_httpx import HTTPXMock
+from pytest_httpx import HTTPXBackend, HTTPXMock, get_backends
+
+if TYPE_CHECKING:
+ try:
+ import httpx
+ except ModuleNotFoundError:
+ import httpx2 as httpx
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_without_response(httpx_mock: HTTPXMock) -> None:
+async def test_without_response(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
with pytest.raises(Exception) as exception_info:
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.get("https://test_url")
assert (
str(exception_info.value)
@@ -28,31 +33,33 @@ async def test_without_response(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_default_response(httpx_mock: HTTPXMock) -> None:
+async def test_default_response(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response()
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.content == b""
assert response.status_code == 200
- assert response.headers == httpx.Headers({})
+ assert response.headers == backend.httpx.Headers({})
assert response.http_version == "HTTP/1.1"
@pytest.mark.asyncio
-async def test_url_matching(httpx_mock: HTTPXMock) -> None:
+async def test_url_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(url="https://test_url")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.content == b""
@pytest.mark.asyncio
-async def test_url_matching_reusing_response(httpx_mock: HTTPXMock) -> None:
+async def test_url_matching_reusing_response(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url", is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.content == b""
@@ -61,10 +68,12 @@ async def test_url_matching_reusing_response(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_url_query_string_matching(httpx_mock: HTTPXMock) -> None:
+async def test_url_query_string_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url?a=1&b=2", is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.post("https://test_url?a=1&b=2")
assert response.content == b""
@@ -73,13 +82,12 @@ async def test_url_query_string_matching(httpx_mock: HTTPXMock) -> None:
assert response.content == b""
-@pytest.mark.asyncio
@pytest.mark.parametrize("sequence_type", [list, tuple])
async def test_url_query_params_partial_matching(
- httpx_mock: HTTPXMock, sequence_type: type
+ httpx_mock: HTTPXMock, backend: HTTPXBackend, sequence_type: type
) -> None:
httpx_mock.add_response(
- url=httpx.URL("https://test_url"),
+ url=backend.httpx.URL("https://test_url"),
match_params={
"a": sequence_type(["1", "3"]),
"b": ANY,
@@ -90,7 +98,7 @@ async def test_url_query_params_partial_matching(
is_reusable=True,
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.post("https://test_url?a=1&b=2&a=3&c=4&d=5&d=6&e=7")
assert response.content == b""
@@ -100,51 +108,59 @@ async def test_url_query_params_partial_matching(
@pytest.mark.asyncio
-async def test_url_as_pattern_ignoring_query_parameters(httpx_mock: HTTPXMock):
+async def test_url_as_pattern_ignoring_query_parameters(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+):
httpx_mock.add_response(url=re.compile("https://test_url/something.*"))
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url/something?a=1&b=2")
assert response.content == b""
@pytest.mark.asyncio
-async def test_url_query_params_with_single_value_list(httpx_mock: HTTPXMock) -> None:
+async def test_url_query_params_with_single_value_list(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url",
match_params={"a": ["1"]},
is_optional=True,
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.post("https://test_url?a=1")
assert response.content == b""
@pytest.mark.asyncio
-async def test_url_query_params_with_non_str_name(httpx_mock: HTTPXMock) -> None:
+async def test_url_query_params_with_non_str_name(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url",
match_params={1: "1"},
is_optional=True,
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.post("https://test_url?1=1")
assert response.content == b""
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_url_query_params_not_matching(httpx_mock: HTTPXMock) -> None:
+async def test_url_query_params_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url",
match_params={"a": "1"},
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url?a=2")
assert (
str(exception_info.value)
@@ -210,10 +226,11 @@ async def test_match_params_with_non_str_values_and_params_provided_as_dict(
httpx_mock: HTTPXMock,
match_params: dict[str, Any],
request_params: dict[str, Any],
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(url="https://test_url", match_params=match_params)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url", params=request_params)
assert response.content == b""
@@ -259,10 +276,11 @@ async def test_match_params_with_non_str_values_and_params_in_requested_url(
httpx_mock: HTTPXMock,
match_params: dict[str, Any],
url: str,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(url="https://test_url", match_params=match_params)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get(url)
assert response.content == b""
@@ -270,10 +288,11 @@ async def test_match_params_with_non_str_values_and_params_in_requested_url(
@pytest.mark.asyncio
async def test_url_matching_with_more_than_one_value_on_same_param(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(url="https://test_url?a=1&a=3", is_optional=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url", params={"a": [1, 3]})
assert response.content == b""
@@ -282,11 +301,12 @@ async def test_url_matching_with_more_than_one_value_on_same_param(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_url_not_matching_with_more_than_one_value_on_same_param_and_diff_value(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(url="https://test_url?a=2&a=3", is_optional=True)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.get("https://test_url", params={"a": [1, 3]})
assert (
str(exception_info.value)
@@ -299,11 +319,12 @@ async def test_url_not_matching_with_more_than_one_value_on_same_param_and_diff_
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_url_not_matching_with_more_than_one_value_on_same_param_and_more_values(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(url="https://test_url?a=1&a=3", is_optional=True)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.get("https://test_url", params={"a": [1, 3, 4]})
assert (
str(exception_info.value)
@@ -316,11 +337,12 @@ async def test_url_not_matching_with_more_than_one_value_on_same_param_and_more_
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_url_not_matching_with_more_than_one_value_on_same_param_and_less_values(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(url="https://test_url?a=1&a=3&a=4", is_optional=True)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.get("https://test_url", params={"a": [1, 3]})
assert (
str(exception_info.value)
@@ -331,11 +353,11 @@ async def test_url_not_matching_with_more_than_one_value_on_same_param_and_less_
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_url_not_matching(httpx_mock: HTTPXMock) -> None:
+async def test_url_not_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(url="https://test_url", is_optional=True)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.get("https://test_url2")
assert (
str(exception_info.value)
@@ -346,11 +368,13 @@ async def test_url_not_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_url_query_string_not_matching(httpx_mock: HTTPXMock) -> None:
+async def test_url_query_string_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url?a=1&a=2", is_optional=True)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
# Same parameter order matters as it corresponds to a list on server side
await client.get("https://test_url?a=2&a=1")
assert (
@@ -361,10 +385,10 @@ async def test_url_query_string_not_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_method_matching(httpx_mock: HTTPXMock) -> None:
+async def test_method_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(method="get", is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.content == b""
@@ -374,11 +398,13 @@ async def test_method_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_method_not_matching(httpx_mock: HTTPXMock) -> None:
+async def test_method_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(method="get", is_optional=True)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url")
assert (
str(exception_info.value)
@@ -388,12 +414,14 @@ async def test_method_not_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_reusing_one_response(httpx_mock: HTTPXMock) -> None:
+async def test_reusing_one_response(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url", content=b"test content", is_reusable=True
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.content == b"test content"
@@ -402,39 +430,45 @@ async def test_reusing_one_response(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_response_with_string_body(httpx_mock: HTTPXMock) -> None:
+async def test_response_with_string_body(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url", text="test content")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.content == b"test content"
@pytest.mark.asyncio
-async def test_response_with_html_string_body(httpx_mock: HTTPXMock) -> None:
+async def test_response_with_html_string_body(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url", html="
test content")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.content == b"test content"
@pytest.mark.asyncio
-async def test_stream_response_streaming(httpx_mock: HTTPXMock) -> None:
+async def test_stream_response_streaming(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url",
stream=pytest_httpx.IteratorStream([b"part 1", b"part 2"]),
is_reusable=True,
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
async with client.stream(method="GET", url="https://test_url") as response:
assert [part async for part in response.aiter_raw()] == [
b"part 1",
b"part 2",
]
# Assert that stream still behaves the proper way (can only be consumed once per request)
- with pytest.raises(httpx.StreamConsumed):
+ with pytest.raises(backend.httpx.StreamConsumed):
async for _ in response.aiter_raw():
pass # pragma: no cover
@@ -444,26 +478,28 @@ async def test_stream_response_streaming(httpx_mock: HTTPXMock) -> None:
b"part 2",
]
# Assert that stream still behaves the proper way (can only be consumed once per request)
- with pytest.raises(httpx.StreamConsumed):
+ with pytest.raises(backend.httpx.StreamConsumed):
async for _ in response.aiter_raw():
pass # pragma: no cover
@pytest.mark.asyncio
-async def test_content_response_streaming(httpx_mock: HTTPXMock) -> None:
+async def test_content_response_streaming(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url",
content=b"part 1 and 2",
is_reusable=True,
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
async with client.stream(method="GET", url="https://test_url") as response:
assert [part async for part in response.aiter_raw()] == [
b"part 1 and 2",
]
# Assert that stream still behaves the proper way (can only be consumed once per request)
- with pytest.raises(httpx.StreamConsumed):
+ with pytest.raises(backend.httpx.StreamConsumed):
async for _ in response.aiter_raw():
pass # pragma: no cover
@@ -472,26 +508,28 @@ async def test_content_response_streaming(httpx_mock: HTTPXMock) -> None:
b"part 1 and 2",
]
# Assert that stream still behaves the proper way (can only be consumed once per request)
- with pytest.raises(httpx.StreamConsumed):
+ with pytest.raises(backend.httpx.StreamConsumed):
async for _ in response.aiter_raw():
pass # pragma: no cover
@pytest.mark.asyncio
-async def test_text_response_streaming(httpx_mock: HTTPXMock) -> None:
+async def test_text_response_streaming(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url",
text="part 1 and 2",
is_reusable=True,
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
async with client.stream(method="GET", url="https://test_url") as response:
assert [part async for part in response.aiter_raw()] == [
b"part 1 and 2",
]
# Assert that stream still behaves the proper way (can only be consumed once per request)
- with pytest.raises(httpx.StreamConsumed):
+ with pytest.raises(backend.httpx.StreamConsumed):
async for _ in response.aiter_raw():
pass # pragma: no cover
@@ -500,38 +538,42 @@ async def test_text_response_streaming(httpx_mock: HTTPXMock) -> None:
b"part 1 and 2",
]
# Assert that stream still behaves the proper way (can only be consumed once per request)
- with pytest.raises(httpx.StreamConsumed):
+ with pytest.raises(backend.httpx.StreamConsumed):
async for _ in response.aiter_raw():
pass # pragma: no cover
@pytest.mark.asyncio
-async def test_default_response_streaming(httpx_mock: HTTPXMock) -> None:
+async def test_default_response_streaming(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
async with client.stream(method="GET", url="https://test_url") as response:
assert [part async for part in response.aiter_raw()] == []
# Assert that stream still behaves the proper way (can only be consumed once per request)
- with pytest.raises(httpx.StreamConsumed):
+ with pytest.raises(backend.httpx.StreamConsumed):
async for _ in response.aiter_raw():
pass # pragma: no cover
async with client.stream(method="GET", url="https://test_url") as response:
assert [part async for part in response.aiter_raw()] == []
# Assert that stream still behaves the proper way (can only be consumed once per request)
- with pytest.raises(httpx.StreamConsumed):
+ with pytest.raises(backend.httpx.StreamConsumed):
async for _ in response.aiter_raw():
pass # pragma: no cover
@pytest.mark.asyncio
-async def test_with_many_responses(httpx_mock: HTTPXMock) -> None:
+async def test_with_many_responses(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url", content=b"test content 1")
httpx_mock.add_response(url="https://test_url", content=b"test content 2")
httpx_mock.add_response(url="https://test_url", content=b"test content 2")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.content == b"test content 1"
@@ -543,13 +585,15 @@ async def test_with_many_responses(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_with_many_reused_responses(httpx_mock: HTTPXMock) -> None:
+async def test_with_many_reused_responses(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url", content=b"test content 1")
httpx_mock.add_response(
url="https://test_url", content=b"test content 2", is_reusable=True
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.content == b"test content 1"
@@ -561,7 +605,9 @@ async def test_with_many_reused_responses(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_with_many_responses_methods(httpx_mock: HTTPXMock) -> None:
+async def test_with_many_responses_methods(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url", method="GET", content=b"test content 1"
)
@@ -581,7 +627,7 @@ async def test_with_many_responses_methods(httpx_mock: HTTPXMock) -> None:
url="https://test_url", method="HEAD", content=b"test content 6"
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.post("https://test_url")
assert response.content == b"test content 2"
@@ -602,7 +648,9 @@ async def test_with_many_responses_methods(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_with_many_responses_status_codes(httpx_mock: HTTPXMock) -> None:
+async def test_with_many_responses_status_codes(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url", method="GET", content=b"test content 1", status_code=200
)
@@ -634,7 +682,7 @@ async def test_with_many_responses_status_codes(httpx_mock: HTTPXMock) -> None:
status_code=500,
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.post("https://test_url")
assert response.content == b"test content 2"
assert response.status_code == 201
@@ -661,7 +709,9 @@ async def test_with_many_responses_status_codes(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_with_many_responses_urls_str(httpx_mock: HTTPXMock) -> None:
+async def test_with_many_responses_urls_str(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url?param1=test", method="GET", content=b"test content 1"
)
@@ -681,44 +731,46 @@ async def test_with_many_responses_urls_str(httpx_mock: HTTPXMock) -> None:
url="https://test_url?param6=test", method="HEAD", content=b"test content 6"
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.post(
- httpx.URL("https://test_url", params={"param2": "test"})
+ backend.httpx.URL("https://test_url", params={"param2": "test"})
)
assert response.content == b"test content 2"
response = await client.get(
- httpx.URL("https://test_url", params={"param1": "test"})
+ backend.httpx.URL("https://test_url", params={"param1": "test"})
)
assert response.content == b"test content 1"
response = await client.put(
- httpx.URL("https://test_url", params={"param3": "test"})
+ backend.httpx.URL("https://test_url", params={"param3": "test"})
)
assert response.content == b"test content 3"
response = await client.head(
- httpx.URL("https://test_url", params={"param6": "test"})
+ backend.httpx.URL("https://test_url", params={"param6": "test"})
)
assert response.content == b"test content 6"
response = await client.patch(
- httpx.URL("https://test_url", params={"param5": "test"})
+ backend.httpx.URL("https://test_url", params={"param5": "test"})
)
assert response.content == b"test content 5"
response = await client.delete(
- httpx.URL("https://test_url", params={"param4": "test"})
+ backend.httpx.URL("https://test_url", params={"param4": "test"})
)
assert response.content == b"test content 4"
@pytest.mark.asyncio
-async def test_response_with_pattern_in_url(httpx_mock: HTTPXMock) -> None:
+async def test_response_with_pattern_in_url(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url=re.compile(".*test.*"))
httpx_mock.add_response(url="https://unmatched", content=b"test content")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://unmatched")
assert response.content == b"test content"
@@ -727,11 +779,13 @@ async def test_response_with_pattern_in_url(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_request_with_pattern_in_url(httpx_mock: HTTPXMock) -> None:
+async def test_request_with_pattern_in_url(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url")
httpx_mock.add_response(url="https://unmatched")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.get("https://unmatched")
await client.get("https://test_url", headers={"X-Test": "1"})
@@ -741,12 +795,14 @@ async def test_request_with_pattern_in_url(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_requests_with_pattern_in_url(httpx_mock: HTTPXMock) -> None:
+async def test_requests_with_pattern_in_url(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url")
httpx_mock.add_response(url="https://tests_url")
httpx_mock.add_response(url="https://unmatched")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.get("https://tests_url", headers={"X-Test": "1"})
await client.get("https://unmatched", headers={"X-Test": "2"})
await client.get("https://test_url")
@@ -758,12 +814,14 @@ async def test_requests_with_pattern_in_url(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_callback_with_pattern_in_url(httpx_mock: HTTPXMock) -> None:
- def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json={"url": str(request.url)})
+async def test_callback_with_pattern_in_url(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+ def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json={"url": str(request.url)})
- def custom_response2(request: httpx.Request) -> httpx.Response:
- return httpx.Response(
+ def custom_response2(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(
status_code=200,
extensions={"http_version": b"HTTP/2.0"},
json={"url": str(request.url)},
@@ -772,7 +830,7 @@ def custom_response2(request: httpx.Request) -> httpx.Response:
httpx_mock.add_callback(custom_response, url=re.compile(".*test.*"))
httpx_mock.add_callback(custom_response2, url="https://unmatched")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://unmatched")
assert response.http_version == "HTTP/2.0"
@@ -781,16 +839,18 @@ def custom_response2(request: httpx.Request) -> httpx.Response:
@pytest.mark.asyncio
-async def test_async_callback_with_await_statement(httpx_mock: HTTPXMock) -> None:
- async def simulate_network_latency(request: httpx.Request):
+async def test_async_callback_with_await_statement(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+ async def simulate_network_latency(request: "httpx.Request"):
await asyncio.sleep(1)
- return httpx.Response(
+ return backend.httpx.Response(
status_code=200,
json={"url": str(request.url), "time": time.time()},
)
- def instant_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(
+ def instant_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(
status_code=200, json={"url": str(request.url), "time": time.time()}
)
@@ -798,7 +858,7 @@ def instant_response(request: httpx.Request) -> httpx.Response:
httpx_mock.add_callback(instant_response)
httpx_mock.add_response(json={"url": "not a callback"})
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
responses = await asyncio.gather(
client.get("https://slow"),
client.get("https://fast_with_callback"),
@@ -818,12 +878,16 @@ def instant_response(request: httpx.Request) -> httpx.Response:
@pytest.mark.asyncio
-async def test_async_callback_with_pattern_in_url(httpx_mock: HTTPXMock) -> None:
- async def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json={"url": str(request.url)})
+async def test_async_callback_with_pattern_in_url(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+ async def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json={"url": str(request.url)})
- async def custom_response2(request: httpx.Request) -> httpx.Response:
- return httpx.Response(
+ async def custom_response2(
+ request: "httpx.Request",
+ ) -> "httpx.Response":
+ return backend.httpx.Response(
status_code=200,
extensions={"http_version": b"HTTP/2.0"},
json={"url": str(request.url)},
@@ -832,7 +896,7 @@ async def custom_response2(request: httpx.Request) -> httpx.Response:
httpx_mock.add_callback(custom_response, url=re.compile(".*test.*"))
httpx_mock.add_callback(custom_response2, url="https://unmatched")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://unmatched")
assert response.http_version == "HTTP/2.0"
@@ -841,39 +905,42 @@ async def custom_response2(request: httpx.Request) -> httpx.Response:
@pytest.mark.asyncio
-async def test_with_many_responses_urls_instances(httpx_mock: HTTPXMock) -> None:
+async def test_with_many_responses_urls_instances(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+
httpx_mock.add_response(
- url=httpx.URL("https://test_url", params={"param1": "test"}),
+ url=backend.httpx.URL("https://test_url", params={"param1": "test"}),
method="GET",
content=b"test content 1",
)
httpx_mock.add_response(
- url=httpx.URL("https://test_url", params={"param2": "test"}),
+ url=backend.httpx.URL("https://test_url", params={"param2": "test"}),
method="POST",
content=b"test content 2",
)
httpx_mock.add_response(
- url=httpx.URL("https://test_url", params={"param3": "test"}),
+ url=backend.httpx.URL("https://test_url", params={"param3": "test"}),
method="PUT",
content=b"test content 3",
)
httpx_mock.add_response(
- url=httpx.URL("https://test_url", params={"param4": "test"}),
+ url=backend.httpx.URL("https://test_url", params={"param4": "test"}),
method="DELETE",
content=b"test content 4",
)
httpx_mock.add_response(
- url=httpx.URL("https://test_url", params={"param5": "test"}),
+ url=backend.httpx.URL("https://test_url", params={"param5": "test"}),
method="PATCH",
content=b"test content 5",
)
httpx_mock.add_response(
- url=httpx.URL("https://test_url", params={"param6": "test"}),
+ url=backend.httpx.URL("https://test_url", params={"param6": "test"}),
method="HEAD",
content=b"test content 6",
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.post("https://test_url?param2=test")
assert response.content == b"test content 2"
@@ -894,35 +961,38 @@ async def test_with_many_responses_urls_instances(httpx_mock: HTTPXMock) -> None
@pytest.mark.asyncio
-async def test_with_http_version_2(httpx_mock: HTTPXMock) -> None:
+async def test_with_http_version_2(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url", http_version="HTTP/2", content=b"test content 1"
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.content == b"test content 1"
assert response.http_version == "HTTP/2"
@pytest.mark.asyncio
-async def test_with_headers(httpx_mock: HTTPXMock) -> None:
+async def test_with_headers(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(
url="https://test_url",
content=b"test content 1",
headers={"X-Test": "Test value"},
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.content == b"test content 1"
- assert response.headers == httpx.Headers(
+ assert response.headers == backend.httpx.Headers(
{"x-test": "Test value", "content-length": "14"}
)
@pytest.mark.asyncio
-async def test_requests_retrieval(httpx_mock: HTTPXMock) -> None:
+async def test_requests_retrieval(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
+
httpx_mock.add_response(
url="https://test_url", method="GET", content=b"test content 1"
)
@@ -942,7 +1012,7 @@ async def test_requests_retrieval(httpx_mock: HTTPXMock) -> None:
url="https://test_url", method="HEAD", content=b"test content 6"
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.post("https://test_url", content=b"sent content 2")
await client.get("https://test_url", headers={"X-TEST": "test header 1"})
await client.put("https://test_url", content=b"sent content 3")
@@ -951,74 +1021,80 @@ async def test_requests_retrieval(httpx_mock: HTTPXMock) -> None:
await client.delete("https://test_url", headers={"X-Test": "test header 4"})
patch_request = httpx_mock.get_request(
- url=httpx.URL("https://test_url"), method="PATCH"
+ url=backend.httpx.URL("https://test_url"), method="PATCH"
)
assert patch_request is not None
assert patch_request.read() == b"sent content 5"
head_request = httpx_mock.get_request(
- url=httpx.URL("https://test_url"), method="HEAD"
+ url=backend.httpx.URL("https://test_url"), method="HEAD"
)
assert head_request is not None
assert head_request.read() == b""
put_request = httpx_mock.get_request(
- url=httpx.URL("https://test_url"), method="PUT"
+ url=backend.httpx.URL("https://test_url"), method="PUT"
)
assert put_request is not None
assert put_request.read() == b"sent content 3"
get_request = httpx_mock.get_request(
- url=httpx.URL("https://test_url"), method="GET"
+ url=backend.httpx.URL("https://test_url"), method="GET"
)
assert get_request is not None
assert get_request.headers["x-test"] == "test header 1"
post_request = httpx_mock.get_request(
- url=httpx.URL("https://test_url"), method="POST"
+ url=backend.httpx.URL("https://test_url"), method="POST"
)
assert post_request is not None
assert post_request.read() == b"sent content 2"
delete_request = httpx_mock.get_request(
- url=httpx.URL("https://test_url"), method="DELETE"
+ url=backend.httpx.URL("https://test_url"), method="DELETE"
)
assert delete_request is not None
assert delete_request.headers["x-test"] == "test header 4"
@pytest.mark.asyncio
-async def test_requests_retrieval_on_same_url(httpx_mock: HTTPXMock) -> None:
+async def test_requests_retrieval_on_same_url(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url", is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.get("https://test_url", headers={"X-TEST": "test header 1"})
await client.get("https://test_url", headers={"X-TEST": "test header 2"})
- requests = httpx_mock.get_requests(url=httpx.URL("https://test_url"))
+ requests = httpx_mock.get_requests(url=backend.httpx.URL("https://test_url"))
assert len(requests) == 2
assert requests[0].headers["x-test"] == "test header 1"
assert requests[1].headers["x-test"] == "test header 2"
@pytest.mark.asyncio
-async def test_request_retrieval_on_same_url(httpx_mock: HTTPXMock) -> None:
+async def test_request_retrieval_on_same_url(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.get("https://test_url", headers={"X-TEST": "test header 1"})
await client.get("https://test_url2", headers={"X-TEST": "test header 2"})
- request = httpx_mock.get_request(url=httpx.URL("https://test_url"))
+ request = httpx_mock.get_request(url=backend.httpx.URL("https://test_url"))
assert request is not None
assert request.headers["x-test"] == "test header 1"
@pytest.mark.asyncio
-async def test_requests_retrieval_on_same_method(httpx_mock: HTTPXMock) -> None:
+async def test_requests_retrieval_on_same_method(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.get("https://test_url", headers={"X-TEST": "test header 1"})
await client.get("https://test_url2", headers={"X-TEST": "test header 2"})
@@ -1029,10 +1105,12 @@ async def test_requests_retrieval_on_same_method(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_request_retrieval_on_same_method(httpx_mock: HTTPXMock) -> None:
+async def test_request_retrieval_on_same_method(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.get("https://test_url", headers={"X-TEST": "test header 1"})
await client.post("https://test_url", headers={"X-TEST": "test header 2"})
@@ -1042,26 +1120,32 @@ async def test_request_retrieval_on_same_method(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_requests_retrieval_on_same_url_and_method(httpx_mock: HTTPXMock) -> None:
+async def test_requests_retrieval_on_same_url_and_method(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.get("https://test_url", headers={"X-TEST": "test header 1"})
await client.get("https://test_url", headers={"X-TEST": "test header 2"})
await client.post("https://test_url", headers={"X-TEST": "test header 3"})
await client.get("https://test_url2", headers={"X-TEST": "test header 4"})
- requests = httpx_mock.get_requests(url=httpx.URL("https://test_url"), method="GET")
+ requests = httpx_mock.get_requests(
+ url=backend.httpx.URL("https://test_url"), method="GET"
+ )
assert len(requests) == 2
assert requests[0].headers["x-test"] == "test header 1"
assert requests[1].headers["x-test"] == "test header 2"
@pytest.mark.asyncio
-async def test_default_requests_retrieval(httpx_mock: HTTPXMock) -> None:
+async def test_default_requests_retrieval(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.post("https://test_url", headers={"X-TEST": "test header 1"})
await client.get("https://test_url2", headers={"X-TEST": "test header 2"})
@@ -1072,10 +1156,12 @@ async def test_default_requests_retrieval(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_default_request_retrieval(httpx_mock: HTTPXMock) -> None:
+async def test_default_request_retrieval(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response()
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.post("https://test_url", headers={"X-TEST": "test header 1"})
request = httpx_mock.get_request()
@@ -1084,7 +1170,7 @@ async def test_default_request_retrieval(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_requests_json_body(httpx_mock: HTTPXMock) -> None:
+async def test_requests_json_body(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(
url="https://test_url", method="GET", json=["list content 1", "list content 2"]
)
@@ -1095,7 +1181,7 @@ async def test_requests_json_body(httpx_mock: HTTPXMock) -> None:
)
httpx_mock.add_response(url="https://test_url", method="PUT", json="string value")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.post("https://test_url")
assert response.json() == {"key 1": "value 1", "key 2": "value 2"}
assert response.headers["content-type"] == "application/json"
@@ -1110,85 +1196,107 @@ async def test_requests_json_body(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_callback_raising_exception(httpx_mock: HTTPXMock) -> None:
- def raise_timeout(request: httpx.Request) -> httpx.Response:
- raise httpx.ReadTimeout(
+async def test_callback_raising_exception(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+
+ def raise_timeout(request: "httpx.Request") -> "httpx.Response":
+ raise backend.httpx.ReadTimeout(
f"Unable to read within {request.extensions['timeout']['read']}",
request=request,
)
httpx_mock.add_callback(raise_timeout, url="https://test_url")
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.ReadTimeout) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.ReadTimeout) as exception_info:
await client.get("https://test_url")
assert str(exception_info.value) == "Unable to read within 5.0"
@pytest.mark.asyncio
-async def test_async_callback_raising_exception(httpx_mock: HTTPXMock) -> None:
- async def raise_timeout(request: httpx.Request) -> httpx.Response:
- raise httpx.ReadTimeout(
+async def test_async_callback_raising_exception(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+
+ async def raise_timeout(request: "httpx.Request") -> "httpx.Response":
+ raise backend.httpx.ReadTimeout(
f"Unable to read within {request.extensions['timeout']['read']}",
request=request,
)
httpx_mock.add_callback(raise_timeout, url="https://test_url")
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.ReadTimeout) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.ReadTimeout) as exception_info:
await client.get("https://test_url")
assert str(exception_info.value) == "Unable to read within 5.0"
@pytest.mark.asyncio
-async def test_request_exception_raising(httpx_mock: HTTPXMock) -> None:
+async def test_request_exception_raising(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_exception(
- httpx.ReadTimeout("Unable to read within 5.0"), url="https://test_url"
+ backend.httpx.ReadTimeout("Unable to read within 5.0"), url="https://test_url"
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.ReadTimeout) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.ReadTimeout) as exception_info:
await client.get("https://test_url")
assert str(exception_info.value) == "Unable to read within 5.0"
assert exception_info.value.request is not None
+@pytest.fixture
+def _non_request_exception_raising_errors(
+ request: pytest.FixtureRequest, backend: HTTPXBackend
+) -> tuple[type[BaseException], str]:
+ if request.param == "http":
+ return backend.httpx.HTTPError, "Unable to read within 5.0"
+
+ if request.param == "cancelled":
+ return asyncio.CancelledError, "Request was cancelled"
+
+ raise ValueError(
+ f'Invalid param {request.param}, must be either "http" or "cancelled".'
+ )
+
+
@pytest.mark.asyncio
@pytest.mark.parametrize(
- ("exception_type", "message"),
+ "_non_request_exception_raising_errors",
[
# httpx exception without request context
- pytest.param(
- httpx.HTTPError, "Unable to read within 5.0", id="non_request_exception"
- ),
+ pytest.param("http", id="non_request_exception"),
# BaseException derived exception
- pytest.param(
- asyncio.CancelledError,
- "Request was cancelled",
- id="cancelled_exception",
- ),
+ pytest.param("cancelled", id="cancelled_exception"),
],
+ indirect=True,
)
async def test_non_request_exception_raising(
- httpx_mock: HTTPXMock, exception_type: type, message: str
+ httpx_mock: HTTPXMock, _non_request_exception_raising_errors, backend: HTTPXBackend
) -> None:
- httpx_mock.add_exception(exception_type(message), url="https://test_url")
+ [exc_type, message] = _non_request_exception_raising_errors
+ httpx_mock.add_exception(exc_type(message), url="https://test_url")
- async with httpx.AsyncClient() as client:
- with pytest.raises(exception_type) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(exc_type) as exception_info:
await client.get("https://test_url")
assert str(exception_info.value) == message
@pytest.mark.asyncio
-async def test_callback_returning_response(httpx_mock: HTTPXMock) -> None:
- def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json={"url": str(request.url)})
+async def test_callback_returning_response(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+
+ def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json={"url": str(request.url)})
httpx_mock.add_callback(custom_response, url="https://test_url")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.json() == {"url": "https://test_url"}
assert response.headers["content-type"] == "application/json"
@@ -1198,16 +1306,16 @@ def custom_response(request: httpx.Request) -> httpx.Response:
@pytest.mark.parametrize("return_value", [None, "not a response"])
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_callback_not_returning_a_response(
- httpx_mock: HTTPXMock, return_value: str | None
+ httpx_mock: HTTPXMock, return_value: str | None, backend: HTTPXBackend
) -> None:
httpx_mock.add_callback(lambda request: return_value, url="https://test_url")
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.get("https://test_url")
assert (
str(exception_info.value)
- == "Callback registered for GET request on https://test_url MUST return httpx.Response"
+ == f"Callback registered for GET request on https://test_url MUST return {backend.name}.Response"
)
@@ -1215,43 +1323,52 @@ async def test_callback_not_returning_a_response(
@pytest.mark.parametrize("return_value", [None, "not a response"])
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_async_callback_not_returning_a_response(
- httpx_mock: HTTPXMock, return_value: str | None
+ httpx_mock: HTTPXMock, return_value: str | None, backend: HTTPXBackend
) -> None:
- async def invalid_response(request: httpx.Request) -> httpx.Response:
+
+ async def invalid_response(
+ request: "httpx.Request",
+ ) -> "httpx.Response":
return return_value
httpx_mock.add_callback(invalid_response, url="https://test_url")
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.get("https://test_url")
assert (
str(exception_info.value)
- == "Callback registered for GET request on https://test_url MUST return httpx.Response"
+ == f"Callback registered for GET request on https://test_url MUST return {backend.name}.Response"
)
@pytest.mark.asyncio
-async def test_async_callback_returning_response(httpx_mock: HTTPXMock) -> None:
- async def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json={"url": str(request.url)})
+async def test_async_callback_returning_response(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+
+ async def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json={"url": str(request.url)})
httpx_mock.add_callback(custom_response, url="https://test_url")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.json() == {"url": "https://test_url"}
assert response.headers["content-type"] == "application/json"
@pytest.mark.asyncio
-async def test_callback_executed_twice(httpx_mock: HTTPXMock) -> None:
- def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json=["content"])
+async def test_callback_executed_twice(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+
+ def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json=["content"])
httpx_mock.add_callback(custom_response, is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.json() == ["content"]
assert response.headers["content-type"] == "application/json"
@@ -1262,13 +1379,16 @@ def custom_response(request: httpx.Request) -> httpx.Response:
@pytest.mark.asyncio
-async def test_async_callback_executed_twice(httpx_mock: HTTPXMock) -> None:
- async def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json=["content"])
+async def test_async_callback_executed_twice(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+
+ async def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json=["content"])
httpx_mock.add_callback(custom_response, is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.json() == ["content"]
assert response.headers["content-type"] == "application/json"
@@ -1279,14 +1399,17 @@ async def custom_response(request: httpx.Request) -> httpx.Response:
@pytest.mark.asyncio
-async def test_callback_registered_after_response(httpx_mock: HTTPXMock) -> None:
- def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json=["content2"])
+async def test_callback_registered_after_response(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+
+ def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json=["content2"])
httpx_mock.add_response(json=["content1"])
httpx_mock.add_callback(custom_response, is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.json() == ["content1"]
assert response.headers["content-type"] == "application/json"
@@ -1302,14 +1425,17 @@ def custom_response(request: httpx.Request) -> httpx.Response:
@pytest.mark.asyncio
-async def test_async_callback_registered_after_response(httpx_mock: HTTPXMock) -> None:
- async def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json=["content2"])
+async def test_async_callback_registered_after_response(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+
+ async def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json=["content2"])
httpx_mock.add_response(json=["content1"])
httpx_mock.add_callback(custom_response, is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.json() == ["content1"]
assert response.headers["content-type"] == "application/json"
@@ -1325,14 +1451,17 @@ async def custom_response(request: httpx.Request) -> httpx.Response:
@pytest.mark.asyncio
-async def test_response_registered_after_callback(httpx_mock: HTTPXMock) -> None:
- def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json=["content1"])
+async def test_response_registered_after_callback(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+
+ def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json=["content1"])
httpx_mock.add_callback(custom_response)
httpx_mock.add_response(json=["content2"], is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.json() == ["content1"]
assert response.headers["content-type"] == "application/json"
@@ -1348,14 +1477,17 @@ def custom_response(request: httpx.Request) -> httpx.Response:
@pytest.mark.asyncio
-async def test_response_registered_after_async_callback(httpx_mock: HTTPXMock) -> None:
- async def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json=["content1"])
+async def test_response_registered_after_async_callback(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+
+ async def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json=["content1"])
httpx_mock.add_callback(custom_response)
httpx_mock.add_response(json=["content2"], is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.json() == ["content1"]
assert response.headers["content-type"] == "application/json"
@@ -1371,13 +1503,16 @@ async def custom_response(request: httpx.Request) -> httpx.Response:
@pytest.mark.asyncio
-async def test_callback_matching_method(httpx_mock: HTTPXMock) -> None:
- def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json=["content"])
+async def test_callback_matching_method(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+
+ def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json=["content"])
httpx_mock.add_callback(custom_response, method="GET", is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.json() == ["content"]
assert response.headers["content-type"] == "application/json"
@@ -1388,13 +1523,16 @@ def custom_response(request: httpx.Request) -> httpx.Response:
@pytest.mark.asyncio
-async def test_async_callback_matching_method(httpx_mock: HTTPXMock) -> None:
- async def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json=["content"])
+async def test_async_callback_matching_method(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+
+ async def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json=["content"])
httpx_mock.add_callback(custom_response, method="GET", is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.json() == ["content"]
assert response.headers["content-type"] == "application/json"
@@ -1408,23 +1546,29 @@ def test_request_retrieval_with_more_than_one(testdir: Testdir) -> None:
"""
Single request cannot be returned if there is more than one matching.
"""
- testdir.makepyfile("""
- import httpx
+ testdir.makeconftest("""
import pytest
+ from pytest_httpx import HTTPXBackend, get_backends
+ @pytest.fixture(params=get_backends(), ids=lambda b: b.name)
+ def backend(request):
+ return request.param
+ """)
+ testdir.makepyfile("""
+ import pytest
@pytest.mark.asyncio
- async def test_request_retrieval_with_more_than_one(httpx_mock):
+ async def test_request_retrieval_with_more_than_one(httpx_mock, backend):
httpx_mock.add_response(is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.get("https://test_url", headers={"X-TEST": "test header 1"})
await client.get("https://test_url", headers={"X-TEST": "test header 2"})
- httpx_mock.get_request(url=httpx.URL("https://test_url"))
+ httpx_mock.get_request(url=backend.httpx.URL("https://test_url"))
""")
result = testdir.runpytest()
- result.assert_outcomes(failed=1)
+ result.assert_outcomes(failed=len(get_backends()))
result.stdout.fnmatch_lines(
[
"*AssertionError: More than one request (2) matched, use get_requests instead or refine your filters."
@@ -1433,21 +1577,26 @@ async def test_request_retrieval_with_more_than_one(httpx_mock):
@pytest.mark.asyncio
-async def test_headers_matching(httpx_mock: HTTPXMock) -> None:
+async def test_headers_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
+
httpx_mock.add_response(
- match_headers={"User-Agent": f"python-httpx/{httpx.__version__}"}
+ match_headers={
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}"
+ }
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.content == b""
@pytest.mark.asyncio
-async def test_multi_value_headers_matching(httpx_mock: HTTPXMock) -> None:
+async def test_multi_value_headers_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(match_headers={"my-custom-header": "value1, value2"})
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get(
"https://test_url",
headers=[("my-custom-header", "value1"), ("my-custom-header", "value2")],
@@ -1459,13 +1608,14 @@ async def test_multi_value_headers_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_multi_value_headers_not_matching_single_value_issued(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
match_headers={"my-custom-header": "value1"}, is_optional=True
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.get(
"https://test_url",
headers=[
@@ -1484,13 +1634,14 @@ async def test_multi_value_headers_not_matching_single_value_issued(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_multi_value_headers_not_matching_multi_value_issued(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
match_headers={"my-custom-header": "value1, value2"}, is_optional=True
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.get(
"https://test_url",
headers=[
@@ -1507,41 +1658,49 @@ async def test_multi_value_headers_not_matching_multi_value_issued(
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_headers_matching_respect_case(httpx_mock: HTTPXMock) -> None:
+async def test_headers_matching_respect_case(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+
httpx_mock.add_response(
- match_headers={"user-agent": f"python-httpx/{httpx.__version__}"},
+ match_headers={
+ "user-agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}"
+ },
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.get("https://test_url")
assert (
str(exception_info.value)
- == f"""No response can be found for GET request on https://test_url with {{'User-Agent': 'python-httpx/{httpx.__version__}'}} headers amongst:
-- Match any request with {{'user-agent': 'python-httpx/{httpx.__version__}'}} headers"""
+ == f"""No response can be found for GET request on https://test_url with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers amongst:
+- Match any request with {{'user-agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers"""
)
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_headers_not_matching(httpx_mock: HTTPXMock) -> None:
+async def test_headers_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+
httpx_mock.add_response(
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
"Host2": "test_url",
},
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.get("https://test_url")
assert (
str(exception_info.value)
- == f"""No response can be found for GET request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers amongst:
-- Match any request with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2', 'Host2': 'test_url'}} headers"""
+ == f"""No response can be found for GET request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers amongst:
+- Match any request with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2', 'Host2': 'test_url'}} headers"""
)
@@ -1549,6 +1708,7 @@ async def test_headers_not_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_url_not_matching_upper_case_headers_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
method="GET",
@@ -1556,8 +1716,8 @@ async def test_url_not_matching_upper_case_headers_matching(
match_headers={"MyHeader": "Something"},
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.get("https://test_url", headers={"MyHeader": "Something"})
assert (
str(exception_info.value)
@@ -1567,29 +1727,37 @@ async def test_url_not_matching_upper_case_headers_matching(
@pytest.mark.asyncio
-async def test_content_matching(httpx_mock: HTTPXMock) -> None:
+async def test_content_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(match_content=b"This is the body")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.post("https://test_url", content=b"This is the body")
assert response.read() == b""
@pytest.mark.asyncio
-async def test_proxy_matching_with_authentication(httpx_mock: HTTPXMock) -> None:
+async def test_proxy_matching_with_authentication(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(proxy_url="http://user:pwd@my_other_proxy/")
- async with httpx.AsyncClient(proxy="http://user:pwd@my_other_proxy") as client:
+ async with backend.httpx.AsyncClient(
+ proxy="http://user:pwd@my_other_proxy"
+ ) as client:
response = await client.get("https://test_url")
assert response.read() == b""
@pytest.mark.asyncio
-async def test_proxy_matching_with_custom_proxy_headers(httpx_mock: HTTPXMock) -> None:
+async def test_proxy_matching_with_custom_proxy_headers(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(proxy_url="http://my_test_proxy/")
- async with httpx.AsyncClient(
- proxy=httpx.Proxy("http://my_test_proxy", headers={"X-Something": "value"})
+ async with backend.httpx.AsyncClient(
+ proxy=backend.httpx.Proxy(
+ "http://my_test_proxy", headers={"X-Something": "value"}
+ )
) as client:
response = await client.get("https://test_url")
assert response.read() == b""
@@ -1598,11 +1766,12 @@ async def test_proxy_matching_with_custom_proxy_headers(httpx_mock: HTTPXMock) -
@pytest.mark.asyncio
async def test_proxy_matching_with_authentication_and_custom_proxy_headers(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(proxy_url="http://user:pwd@my_other_proxy/")
- async with httpx.AsyncClient(
- proxy=httpx.Proxy(
+ async with backend.httpx.AsyncClient(
+ proxy=backend.httpx.Proxy(
"http://user:pwd@my_other_proxy", headers={"X-Something": "value"}
)
) as client:
@@ -1612,11 +1781,11 @@ async def test_proxy_matching_with_authentication_and_custom_proxy_headers(
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_proxy_not_matching(httpx_mock: HTTPXMock) -> None:
+async def test_proxy_not_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(proxy_url="http://my_test_proxy", is_optional=True)
- async with httpx.AsyncClient(proxy="http://my_test_proxy") as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient(proxy="http://my_test_proxy") as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.get("http://test_url")
assert (
str(exception_info.value)
@@ -1627,11 +1796,11 @@ async def test_proxy_not_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_proxy_not_existing(httpx_mock: HTTPXMock) -> None:
+async def test_proxy_not_existing(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(proxy_url="http://my_test_proxy", is_optional=True)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.get("http://test_url")
assert (
str(exception_info.value)
@@ -1641,10 +1810,12 @@ async def test_proxy_not_existing(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_requests_retrieval_content_matching(httpx_mock: HTTPXMock) -> None:
+async def test_requests_retrieval_content_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.post("https://test_url", content=b"This is the body")
await client.post("https://test_url2", content=b"This is the body")
await client.post("https://test_url2", content=b"This is the body2")
@@ -1653,10 +1824,12 @@ async def test_requests_retrieval_content_matching(httpx_mock: HTTPXMock) -> Non
@pytest.mark.asyncio
-async def test_requests_retrieval_json_matching(httpx_mock: HTTPXMock) -> None:
+async def test_requests_retrieval_json_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.post("https://test_url", json=["my_str"])
await client.post("https://test_url2", json=["my_str"])
await client.post("https://test_url2", json=["my_str2"])
@@ -1665,13 +1838,15 @@ async def test_requests_retrieval_json_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_requests_retrieval_proxy_matching(httpx_mock: HTTPXMock) -> None:
+async def test_requests_retrieval_proxy_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- async with httpx.AsyncClient(
+ async with backend.httpx.AsyncClient(
mounts={
- "http://": httpx.AsyncHTTPTransport(proxy="http://my_test_proxy"),
- "https://": httpx.AsyncHTTPTransport(
+ "http://": backend.httpx.AsyncHTTPTransport(proxy="http://my_test_proxy"),
+ "https://": backend.httpx.AsyncHTTPTransport(
proxy="http://user:pwd@my_other_proxy"
),
}
@@ -1686,13 +1861,15 @@ async def test_requests_retrieval_proxy_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_request_retrieval_proxy_matching(httpx_mock: HTTPXMock) -> None:
+async def test_request_retrieval_proxy_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- async with httpx.AsyncClient(
+ async with backend.httpx.AsyncClient(
mounts={
- "http://": httpx.AsyncHTTPTransport(proxy="http://my_test_proxy"),
- "https://": httpx.AsyncHTTPTransport(
+ "http://": backend.httpx.AsyncHTTPTransport(proxy="http://my_test_proxy"),
+ "https://": backend.httpx.AsyncHTTPTransport(
proxy="http://user:pwd@my_other_proxy"
),
}
@@ -1707,10 +1884,11 @@ async def test_request_retrieval_proxy_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
async def test_requests_retrieval_files_and_data_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.put(
"https://test_url",
files={"name": ("file_name", b"File content")},
@@ -1739,10 +1917,12 @@ async def test_requests_retrieval_files_and_data_matching(
@pytest.mark.asyncio
-async def test_request_retrieval_files_and_data_matching(httpx_mock: HTTPXMock) -> None:
+async def test_request_retrieval_files_and_data_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.put(
"https://test_url",
files={"name": ("file_name", b"File content")},
@@ -1758,10 +1938,12 @@ async def test_request_retrieval_files_and_data_matching(httpx_mock: HTTPXMock)
@pytest.mark.asyncio
-async def test_requests_retrieval_extensions_matching(httpx_mock: HTTPXMock) -> None:
+async def test_requests_retrieval_extensions_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.get("https://test_url")
await client.get("https://test_url2", timeout=10)
await client.get("https://test_url2", timeout=10)
@@ -1778,11 +1960,13 @@ async def test_requests_retrieval_extensions_matching(httpx_mock: HTTPXMock) ->
@pytest.mark.asyncio
-async def test_request_retrieval_extensions_matching(httpx_mock: HTTPXMock) -> None:
+async def test_request_retrieval_extensions_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- async with httpx.AsyncClient() as client:
- await client.get("https://test_url", timeout=httpx.Timeout(5, read=10))
+ async with backend.httpx.AsyncClient() as client:
+ await client.get("https://test_url", timeout=backend.httpx.Timeout(5, read=10))
await client.get("https://test_url2", timeout=10)
await client.get("http://test_url2", timeout=10)
@@ -1793,11 +1977,13 @@ async def test_request_retrieval_extensions_matching(httpx_mock: HTTPXMock) -> N
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_content_not_matching(httpx_mock: HTTPXMock) -> None:
+async def test_content_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(match_content=b"This is the body", is_optional=True)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body2")
assert (
str(exception_info.value)
@@ -1807,30 +1993,32 @@ async def test_content_not_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_json_matching(httpx_mock: HTTPXMock) -> None:
+async def test_json_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(match_json={"a": 1, "b": 2})
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.post("https://test_url", json={"b": 2, "a": 1})
assert response.read() == b""
@pytest.mark.asyncio
-async def test_json_partial_matching(httpx_mock: HTTPXMock) -> None:
+async def test_json_partial_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(match_json={"a": 1, "b": ANY})
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.post("https://test_url", json={"b": 2, "a": 1})
assert response.read() == b""
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_json_not_matching(httpx_mock: HTTPXMock) -> None:
+async def test_json_not_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(match_json={"a": 1, "b": 2}, is_optional=True)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", json={"c": 3, "b": 2, "a": 1})
assert (
str(exception_info.value)
@@ -1841,15 +2029,17 @@ async def test_json_not_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_headers_and_json_not_matching(httpx_mock: HTTPXMock) -> None:
+async def test_headers_and_json_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
match_json={"a": 1, "b": 2},
match_headers={"foo": "bar"},
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", json={"c": 3, "b": 2, "a": 1})
assert (
str(exception_info.value)
@@ -1860,11 +2050,13 @@ async def test_headers_and_json_not_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_match_json_invalid_json(httpx_mock: HTTPXMock) -> None:
+async def test_match_json_invalid_json(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(match_json={"a": 1, "b": 2}, is_optional=True)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"foobar")
assert (
str(exception_info.value)
@@ -1876,11 +2068,13 @@ async def test_match_json_invalid_json(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
@pytest.mark.parametrize("content", [b'{"a":"\xff"}', b'{"a":"\xc3"}'])
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_match_json_invalid_utf8(httpx_mock: HTTPXMock, content: bytes) -> None:
+async def test_match_json_invalid_utf8(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend, content: bytes
+) -> None:
httpx_mock.add_response(match_json={"a": "value"})
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=content)
assert exception_info.value.request.content == content
assert "No response can be found" in str(exception_info.value)
@@ -1890,11 +2084,13 @@ async def test_match_json_invalid_utf8(httpx_mock: HTTPXMock, content: bytes) ->
@pytest.mark.asyncio
-async def test_match_json_binary_content_fallback(httpx_mock: HTTPXMock) -> None:
+async def test_match_json_binary_content_fallback(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(match_json={"a": "value"}, status_code=201)
httpx_mock.add_response(match_content=b"\xff", status_code=202)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.post("https://test_url", content=b"\xff")
assert response.status_code == 202
response = await client.post("https://test_url", json={"a": "value"})
@@ -1903,11 +2099,11 @@ async def test_match_json_binary_content_fallback(httpx_mock: HTTPXMock) -> None
@pytest.mark.asyncio
async def test_requests_retrieval_json_matching_with_binary_content(
- httpx_mock: HTTPXMock,
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
) -> None:
httpx_mock.add_response(is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
binary_request = (
await client.post("https://test_url", content=b"\xff")
).request
@@ -1921,92 +2117,106 @@ async def test_requests_retrieval_json_matching_with_binary_content(
@pytest.mark.asyncio
-async def test_headers_and_content_matching(httpx_mock: HTTPXMock) -> None:
+async def test_headers_and_content_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
- match_headers={"User-Agent": f"python-httpx/{httpx.__version__}"},
+ match_headers={
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}"
+ },
match_content=b"This is the body",
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.post("https://test_url", content=b"This is the body")
assert response.content == b""
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_headers_not_matching_and_content_matching(httpx_mock: HTTPXMock) -> None:
+async def test_headers_not_matching_and_content_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body",
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
)
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_headers_matching_and_content_not_matching(httpx_mock: HTTPXMock) -> None:
+async def test_headers_matching_and_content_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url",
},
match_content=b"This is the body2",
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
)
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_headers_and_content_not_matching(httpx_mock: HTTPXMock) -> None:
+async def test_headers_and_content_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body2",
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
)
@pytest.mark.asyncio
-async def test_url_and_headers_and_content_matching(httpx_mock: HTTPXMock) -> None:
+async def test_url_and_headers_and_content_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url",
- match_headers={"User-Agent": f"python-httpx/{httpx.__version__}"},
+ match_headers={
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}"
+ },
match_content=b"This is the body",
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.post("https://test_url", content=b"This is the body")
assert response.content == b""
@@ -2015,24 +2225,25 @@ async def test_url_and_headers_and_content_matching(httpx_mock: HTTPXMock) -> No
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_headers_not_matching_and_url_and_content_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body",
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request on https://test_url with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request on https://test_url with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
)
@@ -2040,24 +2251,25 @@ async def test_headers_not_matching_and_url_and_content_matching(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_url_and_headers_not_matching_and_content_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url2",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body",
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request on https://test_url2 with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request on https://test_url2 with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
)
@@ -2065,24 +2277,25 @@ async def test_url_and_headers_not_matching_and_content_matching(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_url_and_headers_matching_and_content_not_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url",
},
match_content=b"This is the body2",
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request on https://test_url with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request on https://test_url with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
)
@@ -2090,24 +2303,25 @@ async def test_url_and_headers_matching_and_content_not_matching(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_headers_matching_and_url_and_content_not_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url2",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url",
},
match_content=b"This is the body2",
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request on https://test_url2 with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request on https://test_url2 with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
)
@@ -2115,62 +2329,68 @@ async def test_headers_matching_and_url_and_content_not_matching(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_url_matching_and_headers_and_content_not_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body2",
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request on https://test_url with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request on https://test_url with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
)
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_url_and_headers_and_content_not_matching(httpx_mock: HTTPXMock) -> None:
+async def test_url_and_headers_and_content_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url2",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body2",
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request on https://test_url2 with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request on https://test_url2 with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
)
@pytest.mark.asyncio
async def test_method_and_url_and_headers_and_content_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url",
method="POST",
- match_headers={"User-Agent": f"python-httpx/{httpx.__version__}"},
+ match_headers={
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}"
+ },
match_content=b"This is the body",
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.post("https://test_url", content=b"This is the body")
assert response.content == b""
@@ -2179,25 +2399,26 @@ async def test_method_and_url_and_headers_and_content_matching(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_headers_not_matching_and_method_and_url_and_content_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url",
method="POST",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body",
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match POST request on https://test_url with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match POST request on https://test_url with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
)
@@ -2205,25 +2426,26 @@ async def test_headers_not_matching_and_method_and_url_and_content_matching(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_url_and_headers_not_matching_and_method_and_content_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url2",
method="POST",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body",
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match POST request on https://test_url2 with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match POST request on https://test_url2 with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
)
@@ -2231,25 +2453,26 @@ async def test_url_and_headers_not_matching_and_method_and_content_matching(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_method_and_url_and_headers_matching_and_content_not_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url",
method="POST",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url",
},
match_content=b"This is the body2",
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match POST request on https://test_url with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match POST request on https://test_url with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
)
@@ -2257,25 +2480,26 @@ async def test_method_and_url_and_headers_matching_and_content_not_matching(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_method_and_headers_matching_and_url_and_content_not_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url2",
method="POST",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url",
},
match_content=b"This is the body2",
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match POST request on https://test_url2 with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match POST request on https://test_url2 with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
)
@@ -2283,25 +2507,26 @@ async def test_method_and_headers_matching_and_url_and_content_not_matching(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_method_and_url_matching_and_headers_and_content_not_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url",
method="POST",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body2",
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match POST request on https://test_url with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match POST request on https://test_url with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
)
@@ -2309,25 +2534,26 @@ async def test_method_and_url_matching_and_headers_and_content_not_matching(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_method_matching_and_url_and_headers_and_content_not_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url2",
method="POST",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body2",
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match POST request on https://test_url2 with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match POST request on https://test_url2 with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
)
@@ -2335,126 +2561,149 @@ async def test_method_matching_and_url_and_headers_and_content_not_matching(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_method_and_url_and_headers_and_content_not_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url2",
method="PUT",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body2",
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match PUT request on https://test_url2 with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match PUT request on https://test_url2 with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
)
@pytest.mark.asyncio
-async def test_header_as_str_tuple_list(httpx_mock: HTTPXMock) -> None:
+async def test_header_as_str_tuple_list(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
headers=[("set-cookie", "key=value"), ("set-cookie", "key2=value2")]
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert dict(response.cookies) == {"key": "value", "key2": "value2"}
@pytest.mark.asyncio
-async def test_header_as_bytes_tuple_list(httpx_mock: HTTPXMock) -> None:
+async def test_header_as_bytes_tuple_list(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
headers=[(b"set-cookie", b"key=value"), (b"set-cookie", b"key2=value2")]
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert dict(response.cookies) == {"key": "value", "key2": "value2"}
@pytest.mark.asyncio
-async def test_header_as_bytes_dict(httpx_mock: HTTPXMock) -> None:
+async def test_header_as_bytes_dict(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(headers={b"set-cookie": b"key=value"})
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert dict(response.cookies) == {"key": "value"}
@pytest.mark.asyncio
-async def test_header_as_httpx_headers(httpx_mock: HTTPXMock) -> None:
- httpx_mock.add_response(headers=httpx.Headers({"set-cookie": "key=value"}))
+async def test_header_as_httpx_headers(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+ httpx_mock.add_response(headers=backend.httpx.Headers({"set-cookie": "key=value"}))
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert dict(response.cookies) == {"key": "value"}
@pytest.mark.asyncio
-async def test_elapsed_when_add_response(httpx_mock: HTTPXMock) -> None:
+async def test_elapsed_when_add_response(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response()
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.elapsed is not None
@pytest.mark.asyncio
-async def test_elapsed_when_add_callback(httpx_mock: HTTPXMock) -> None:
+async def test_elapsed_when_add_callback(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_callback(
- callback=lambda req: httpx.Response(status_code=200, json={"foo": "bar"})
+ callback=lambda req: backend.httpx.Response(
+ status_code=200, json={"foo": "bar"}
+ )
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.elapsed is not None
@pytest.mark.asyncio
-async def test_elapsed_when_add_async_callback(httpx_mock: HTTPXMock) -> None:
- async def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json={"foo": "bar"})
+async def test_elapsed_when_add_async_callback(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+ async def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json={"foo": "bar"})
httpx_mock.add_callback(custom_response)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.elapsed is not None
@pytest.mark.asyncio
-async def test_non_ascii_url_response(httpx_mock: HTTPXMock) -> None:
+async def test_non_ascii_url_response(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url?query_type=数据")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url?query_type=数据")
assert response.content == b""
@pytest.mark.asyncio
-async def test_url_encoded_matching_response(httpx_mock: HTTPXMock) -> None:
+async def test_url_encoded_matching_response(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url?a=%E6%95%B0%E6%8D%AE")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url?a=数据")
assert response.content == b""
@pytest.mark.asyncio
-async def test_reset_is_removing_requests(httpx_mock: HTTPXMock) -> None:
+async def test_reset_is_removing_requests(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response()
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.get("https://test_url")
assert len(httpx_mock.get_requests()) == 1
@@ -2464,14 +2713,14 @@ async def test_reset_is_removing_requests(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_mutating_json(httpx_mock: HTTPXMock) -> None:
+async def test_mutating_json(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
mutating_json = {"content": "request 1"}
httpx_mock.add_response(json=mutating_json)
mutating_json["content"] = "request 2"
httpx_mock.add_response(json=mutating_json)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.json() == {"content": "request 1"}
@@ -2482,32 +2731,35 @@ async def test_mutating_json(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
async def test_streams_are_not_cascading_resulting_in_maximum_recursion(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(json={"abc": "def"}, is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
tasks = [client.get("https://test_url") for _ in range(950)]
await asyncio.gather(*tasks)
# No need to assert anything, this test case ensure that no error was raised by the gather
@pytest.mark.asyncio
-async def test_custom_transport(httpx_mock: HTTPXMock) -> None:
- class CustomTransport(httpx.AsyncHTTPTransport):
+async def test_custom_transport(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
+ class CustomTransport(backend.httpx.AsyncHTTPTransport): # type: ignore[name-defined]
def __init__(self, prefix: str, *args, **kwargs):
super().__init__(*args, **kwargs)
self.prefix = prefix
async def handle_async_request(
self,
- request: httpx.Request,
- ) -> httpx.Response:
+ request: "httpx.Request",
+ ) -> "httpx.Response":
httpx_response = await super().handle_async_request(request)
httpx_response.headers["x-prefix"] = self.prefix
return httpx_response
httpx_mock.add_response()
- async with httpx.AsyncClient(transport=CustomTransport(prefix="test")) as client:
+ async with backend.httpx.AsyncClient(
+ transport=CustomTransport(prefix="test")
+ ) as client:
response = await client.post("https://test_url", content=b"This is the body")
assert response.read() == b""
assert response.headers["x-prefix"] == "test"
@@ -2516,6 +2768,7 @@ async def handle_async_request(
@pytest.mark.asyncio
async def test_response_selection_content_matching_with_async_iterable(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(match_content=b"full content 1", content=b"matched 1")
httpx_mock.add_response(match_content=b"full content 2", content=b"matched 2")
@@ -2532,7 +2785,7 @@ async def stream_content_2() -> AsyncIterable[bytes]:
yield b"content"
yield b" 2"
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response_2 = await client.put("https://test_url", content=stream_content_2())
response_1 = await client.put("https://test_url", content=stream_content_1())
assert response_1.content == b"matched 1"
@@ -2542,6 +2795,7 @@ async def stream_content_2() -> AsyncIterable[bytes]:
@pytest.mark.asyncio
async def test_request_selection_content_matching_with_async_iterable(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(match_content=b"full content 1")
httpx_mock.add_response(match_content=b"full content 2")
@@ -2558,7 +2812,7 @@ async def stream_content_2() -> AsyncIterable[bytes]:
yield b"content"
yield b" 2"
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
await client.put("https://test_url_2", content=stream_content_2())
await client.put("https://test_url_1", content=stream_content_1())
@@ -2572,10 +2826,10 @@ async def stream_content_2() -> AsyncIterable[bytes]:
@pytest.mark.asyncio
-async def test_files_matching(httpx_mock: HTTPXMock) -> None:
+async def test_files_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(match_files={"name": ("file_name", b"File content")})
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.put(
"https://test_url", files={"name": ("file_name", b"File content")}
)
@@ -2583,13 +2837,15 @@ async def test_files_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_files_and_data_matching(httpx_mock: HTTPXMock) -> None:
+async def test_files_and_data_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
match_files={"name": ("file_name", b"File content")},
match_data={"field": "value"},
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.put(
"https://test_url",
files={"name": ("file_name", b"File content")},
@@ -2600,7 +2856,9 @@ async def test_files_and_data_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_files_not_matching_name(httpx_mock: HTTPXMock, monkeypatch) -> None:
+async def test_files_not_matching_name(
+ httpx_mock: HTTPXMock, monkeypatch, backend: HTTPXBackend
+) -> None:
# Ensure generated boundary will be fbe495efe4cd41b941ca13e254d6b018
monkeypatch.setattr(
os,
@@ -2612,8 +2870,8 @@ async def test_files_not_matching_name(httpx_mock: HTTPXMock, monkeypatch) -> No
match_files={"name2": ("file_name", b"File content")}, is_optional=True
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.put(
"https://test_url", files={"name1": ("file_name", b"File content")}
)
@@ -2626,7 +2884,9 @@ async def test_files_not_matching_name(httpx_mock: HTTPXMock, monkeypatch) -> No
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_files_not_matching_file_name(httpx_mock: HTTPXMock, monkeypatch) -> None:
+async def test_files_not_matching_file_name(
+ httpx_mock: HTTPXMock, monkeypatch, backend: HTTPXBackend
+) -> None:
# Ensure generated boundary will be fbe495efe4cd41b941ca13e254d6b018
monkeypatch.setattr(
os,
@@ -2638,8 +2898,8 @@ async def test_files_not_matching_file_name(httpx_mock: HTTPXMock, monkeypatch)
match_files={"name": ("file_name2", b"File content")}, is_optional=True
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.put(
"https://test_url", files={"name": ("file_name1", b"File content")}
)
@@ -2652,7 +2912,9 @@ async def test_files_not_matching_file_name(httpx_mock: HTTPXMock, monkeypatch)
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_files_not_matching_content(httpx_mock: HTTPXMock, monkeypatch) -> None:
+async def test_files_not_matching_content(
+ httpx_mock: HTTPXMock, monkeypatch, backend: HTTPXBackend
+) -> None:
# Ensure generated boundary will be fbe495efe4cd41b941ca13e254d6b018
monkeypatch.setattr(
os,
@@ -2664,8 +2926,8 @@ async def test_files_not_matching_content(httpx_mock: HTTPXMock, monkeypatch) ->
match_files={"name": ("file_name", b"File content2")}, is_optional=True
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.put(
"https://test_url", files={"name": ("file_name", b"File content1")}
)
@@ -2679,7 +2941,7 @@ async def test_files_not_matching_content(httpx_mock: HTTPXMock, monkeypatch) ->
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
async def test_files_matching_but_data_not_matching(
- httpx_mock: HTTPXMock, monkeypatch
+ httpx_mock: HTTPXMock, monkeypatch, backend: HTTPXBackend
) -> None:
# Ensure generated boundary will be fbe495efe4cd41b941ca13e254d6b018
monkeypatch.setattr(
@@ -2694,8 +2956,8 @@ async def test_files_matching_but_data_not_matching(
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.put(
"https://test_url", files={"name": ("file_name", b"File content")}
)
@@ -2707,28 +2969,30 @@ async def test_files_matching_but_data_not_matching(
@pytest.mark.asyncio
-async def test_timeout_matching(httpx_mock: HTTPXMock) -> None:
+async def test_timeout_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(
match_extensions={"timeout": {"connect": 5, "read": 5, "write": 10, "pool": 5}}
)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.put(
- "https://test_url", timeout=httpx.Timeout(5, write=10)
+ "https://test_url", timeout=backend.httpx.Timeout(5, write=10)
)
assert response.content == b""
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_timeout_not_matching(httpx_mock: HTTPXMock) -> None:
+async def test_timeout_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
match_extensions={"timeout": {"connect": 5, "read": 5, "write": 10, "pool": 5}},
is_optional=True,
)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.get("https://test_url", extensions={"test": "value"})
assert (
str(exception_info.value)
@@ -2738,10 +3002,12 @@ async def test_timeout_not_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_extensions_matching(httpx_mock: HTTPXMock) -> None:
+async def test_extensions_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(match_extensions={"test": "value"})
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.put(
"https://test_url", extensions={"test": "value", "test2": "value2"}
)
@@ -2750,11 +3016,13 @@ async def test_extensions_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-async def test_extensions_not_matching(httpx_mock: HTTPXMock) -> None:
+async def test_extensions_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(match_extensions={"test": "value"}, is_optional=True)
- async with httpx.AsyncClient() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ async with backend.httpx.AsyncClient() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
await client.get("https://test_url", extensions={"test": "value2"})
assert (
str(exception_info.value)
@@ -2764,23 +3032,27 @@ async def test_extensions_not_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
-async def test_optional_response_not_matched(httpx_mock: HTTPXMock) -> None:
+async def test_optional_response_not_matched(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
# This response is optional and the fact that it was never requested should not trigger anything
httpx_mock.add_response(url="https://test_url", is_optional=True)
httpx_mock.add_response(url="https://test_url2")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url2")
assert response.content == b""
@pytest.mark.asyncio
-async def test_optional_response_matched(httpx_mock: HTTPXMock) -> None:
+async def test_optional_response_matched(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
# This response is optional and the fact that it was never requested should not trigger anything
httpx_mock.add_response(url="https://test_url", is_optional=True)
httpx_mock.add_response(url="https://test_url2")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response1 = await client.get("https://test_url")
response2 = await client.get("https://test_url2")
assert response1.content == b""
@@ -2789,31 +3061,37 @@ async def test_optional_response_matched(httpx_mock: HTTPXMock) -> None:
@pytest.mark.asyncio
@pytest.mark.httpx_mock(assert_all_responses_were_requested=False)
-async def test_mandatory_response_matched(httpx_mock: HTTPXMock) -> None:
+async def test_mandatory_response_matched(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
# This response is optional and the fact that it was never requested should not trigger anything
httpx_mock.add_response(url="https://test_url")
# This response MUST be requested (overrides global settings via marker)
httpx_mock.add_response(url="https://test_url2", is_optional=False)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url2")
assert response.content == b""
@pytest.mark.asyncio
-async def test_multi_response_matched_once(httpx_mock: HTTPXMock) -> None:
+async def test_multi_response_matched_once(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url", is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.content == b""
@pytest.mark.asyncio
-async def test_multi_response_matched_twice(httpx_mock: HTTPXMock) -> None:
+async def test_multi_response_matched_twice(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url", is_reusable=True)
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
response1 = await client.get("https://test_url")
response2 = await client.get("https://test_url")
assert response1.content == b""
diff --git a/tests/test_httpx_sync.py b/tests/test_httpx_sync.py
index 9f837ca..6ec4de0 100644
--- a/tests/test_httpx_sync.py
+++ b/tests/test_httpx_sync.py
@@ -1,20 +1,25 @@
import os
import re
from collections.abc import Iterable
-from typing import Any
+from typing import TYPE_CHECKING, Any
from unittest.mock import ANY
-import httpx
import pytest
from pytest import Testdir
import pytest_httpx
-from pytest_httpx import HTTPXMock
+from pytest_httpx import HTTPXBackend, HTTPXMock, get_backends
+
+if TYPE_CHECKING:
+ try:
+ import httpx
+ except ModuleNotFoundError:
+ import httpx2 as httpx
@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, httpx.Client() as client:
+def test_without_response(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
+ with pytest.raises(Exception) as exception_info, backend.httpx.Client() as client:
client.get("https://test_url")
assert (
str(exception_info.value)
@@ -22,29 +27,31 @@ def test_without_response(httpx_mock: HTTPXMock) -> None:
)
-def test_default_response(httpx_mock: HTTPXMock) -> None:
+def test_default_response(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response()
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.content == b""
assert response.status_code == 200
- assert response.headers == httpx.Headers({})
+ assert response.headers == backend.httpx.Headers({})
assert response.http_version == "HTTP/1.1"
-def test_url_matching(httpx_mock: HTTPXMock) -> None:
+def test_url_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(url="https://test_url")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.content == b""
-def test_url_matching_reusing_response(httpx_mock: HTTPXMock) -> None:
+def test_url_matching_reusing_response(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url", is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.content == b""
@@ -52,10 +59,12 @@ def test_url_matching_reusing_response(httpx_mock: HTTPXMock) -> None:
assert response.content == b""
-def test_url_query_string_matching(httpx_mock: HTTPXMock) -> None:
+def test_url_query_string_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url?a=1&b=2", is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.post("https://test_url?a=1&b=2")
assert response.content == b""
@@ -66,7 +75,7 @@ def test_url_query_string_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.parametrize("sequence_type", [list, tuple])
def test_url_query_params_partial_matching(
- httpx_mock: HTTPXMock, sequence_type: type
+ httpx_mock: HTTPXMock, backend: HTTPXBackend, sequence_type: type
) -> None:
httpx_mock.add_response(
url="https://test_url",
@@ -80,7 +89,7 @@ def test_url_query_params_partial_matching(
is_reusable=True,
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.post("https://test_url?a=1&b=2&a=3&c=4&d=5&d=6&e=7")
assert response.content == b""
@@ -89,29 +98,35 @@ def test_url_query_params_partial_matching(
assert response.content == b""
-def test_url_as_pattern_ignoring_query_parameters(httpx_mock: HTTPXMock):
+def test_url_as_pattern_ignoring_query_parameters(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+):
httpx_mock.add_response(url=re.compile("https://test_url/something.*"))
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url/something?a=1&b=2")
assert response.content == b""
-def test_url_query_params_with_single_value_list(httpx_mock: HTTPXMock) -> None:
+def test_url_query_params_with_single_value_list(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url", match_params={"a": ["1"]})
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.post("https://test_url?a=1")
assert response.content == b""
-def test_url_query_params_with_non_str_name(httpx_mock: HTTPXMock) -> None:
+def test_url_query_params_with_non_str_name(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url",
match_params={1: "1"},
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.post("https://test_url?1=1")
assert response.content == b""
@@ -146,15 +161,17 @@ def test_regex_url_and_match_params(httpx_mock: HTTPXMock) -> None:
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_url_query_params_not_matching(httpx_mock: HTTPXMock) -> None:
+def test_url_query_params_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url",
match_params={"a": "1"},
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url?a=2")
assert (
str(exception_info.value)
@@ -219,10 +236,11 @@ def test_match_params_with_non_str_values_and_params_provided_as_dict(
httpx_mock: HTTPXMock,
match_params: dict[str, Any],
request_params: dict[str, Any],
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(url="https://test_url", match_params=match_params)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url", params=request_params)
assert response.content == b""
@@ -267,20 +285,22 @@ def test_match_params_with_non_str_values_and_params_in_requested_url(
httpx_mock: HTTPXMock,
match_params: dict[str, Any],
url: str,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(url="https://test_url", match_params=match_params)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get(url)
assert response.content == b""
def test_url_matching_with_more_than_one_value_on_same_param(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(url="https://test_url?a=1&a=3", is_optional=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url", params={"a": [1, 3]})
assert response.content == b""
@@ -288,11 +308,12 @@ def test_url_matching_with_more_than_one_value_on_same_param(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_url_not_matching_with_more_than_one_value_on_same_param_and_diff_value(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(url="https://test_url?a=2&a=3", is_optional=True)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.get("https://test_url", params={"a": [1, 3]})
assert (
str(exception_info.value)
@@ -304,11 +325,12 @@ def test_url_not_matching_with_more_than_one_value_on_same_param_and_diff_value(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_url_not_matching_with_more_than_one_value_on_same_param_and_more_values(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(url="https://test_url?a=1&a=3", is_optional=True)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.get("https://test_url", params={"a": [1, 3, 4]})
assert (
str(exception_info.value)
@@ -320,11 +342,12 @@ def test_url_not_matching_with_more_than_one_value_on_same_param_and_more_values
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_url_not_matching_with_more_than_one_value_on_same_param_and_less_values(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(url="https://test_url?a=1&a=3&a=4", is_optional=True)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.get("https://test_url", params={"a": [1, 3]})
assert (
str(exception_info.value)
@@ -334,11 +357,11 @@ def test_url_not_matching_with_more_than_one_value_on_same_param_and_less_values
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_url_not_matching(httpx_mock: HTTPXMock) -> None:
+def test_url_not_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(url="https://test_url", is_optional=True)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.get("https://test_url2")
assert (
str(exception_info.value)
@@ -348,11 +371,13 @@ def test_url_not_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_url_query_string_not_matching(httpx_mock: HTTPXMock) -> None:
+def test_url_query_string_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url?a=1&a=2", is_optional=True)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
# Same parameter order matters as it corresponds to a list on server side
client.get("https://test_url?a=2&a=1")
assert (
@@ -362,10 +387,10 @@ def test_url_query_string_not_matching(httpx_mock: HTTPXMock) -> None:
)
-def test_method_matching(httpx_mock: HTTPXMock) -> None:
+def test_method_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(method="get", is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.content == b""
@@ -374,11 +399,11 @@ def test_method_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_method_not_matching(httpx_mock: HTTPXMock) -> None:
+def test_method_not_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(method="get", is_optional=True)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url")
assert (
str(exception_info.value)
@@ -387,12 +412,12 @@ def test_method_not_matching(httpx_mock: HTTPXMock) -> None:
)
-def test_reusing_one_response(httpx_mock: HTTPXMock) -> None:
+def test_reusing_one_response(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(
url="https://test_url", content=b"test content", is_reusable=True
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.content == b"test content"
@@ -400,32 +425,38 @@ def test_reusing_one_response(httpx_mock: HTTPXMock) -> None:
assert response.content == b"test content"
-def test_response_with_string_body(httpx_mock: HTTPXMock) -> None:
+def test_response_with_string_body(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url", text="test content")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.content == b"test content"
-def test_response_with_html_string_body(httpx_mock: HTTPXMock) -> None:
+def test_response_with_html_string_body(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url", html="test content")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.text == "test content"
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_url_not_matching_upper_case_headers_matching(httpx_mock: HTTPXMock) -> None:
+def test_url_not_matching_upper_case_headers_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
method="GET",
url="https://test_url?q=b",
match_headers={"MyHeader": "Something"},
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.get("https://test_url", headers={"MyHeader": "Something"})
assert (
str(exception_info.value)
@@ -434,96 +465,102 @@ def test_url_not_matching_upper_case_headers_matching(httpx_mock: HTTPXMock) ->
)
-def test_stream_response_streaming(httpx_mock: HTTPXMock) -> None:
+def test_stream_response_streaming(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url",
stream=pytest_httpx.IteratorStream([b"part 1", b"part 2"]),
is_reusable=True,
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
with client.stream(method="GET", url="https://test_url") as response:
assert list(response.iter_raw()) == [b"part 1", b"part 2"]
# Assert that stream still behaves the proper way (can only be consumed once per request)
- with pytest.raises(httpx.StreamConsumed):
+ with pytest.raises(backend.httpx.StreamConsumed):
list(response.iter_raw())
# Assert a response can be streamed more than once
with client.stream(method="GET", url="https://test_url") as response:
assert list(response.iter_raw()) == [b"part 1", b"part 2"]
# Assert that stream still behaves the proper way (can only be consumed once per request)
- with pytest.raises(httpx.StreamConsumed):
+ with pytest.raises(backend.httpx.StreamConsumed):
list(response.iter_raw())
-def test_content_response_streaming(httpx_mock: HTTPXMock) -> None:
+def test_content_response_streaming(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url",
content=b"part 1 and 2",
is_reusable=True,
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
with client.stream(method="GET", url="https://test_url") as response:
assert list(response.iter_raw()) == [b"part 1 and 2"]
# Assert that stream still behaves the proper way (can only be consumed once per request)
- with pytest.raises(httpx.StreamConsumed):
+ with pytest.raises(backend.httpx.StreamConsumed):
list(response.iter_raw())
# Assert a response can be streamed more than once
with client.stream(method="GET", url="https://test_url") as response:
assert list(response.iter_raw()) == [b"part 1 and 2"]
# Assert that stream still behaves the proper way (can only be consumed once per request)
- with pytest.raises(httpx.StreamConsumed):
+ with pytest.raises(backend.httpx.StreamConsumed):
list(response.iter_raw())
-def test_text_response_streaming(httpx_mock: HTTPXMock) -> None:
+def test_text_response_streaming(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(
url="https://test_url",
text="part 1 and 2",
is_reusable=True,
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
with client.stream(method="GET", url="https://test_url") as response:
assert list(response.iter_raw()) == [b"part 1 and 2"]
# Assert that stream still behaves the proper way (can only be consumed once per request)
- with pytest.raises(httpx.StreamConsumed):
+ with pytest.raises(backend.httpx.StreamConsumed):
list(response.iter_raw())
# Assert a response can be streamed more than once
with client.stream(method="GET", url="https://test_url") as response:
assert list(response.iter_raw()) == [b"part 1 and 2"]
# Assert that stream still behaves the proper way (can only be consumed once per request)
- with pytest.raises(httpx.StreamConsumed):
+ with pytest.raises(backend.httpx.StreamConsumed):
list(response.iter_raw())
-def test_default_response_streaming(httpx_mock: HTTPXMock) -> None:
+def test_default_response_streaming(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
with client.stream(method="GET", url="https://test_url") as response:
assert list(response.iter_raw()) == []
# Assert that stream still behaves the proper way (can only be consumed once per request)
- with pytest.raises(httpx.StreamConsumed):
+ with pytest.raises(backend.httpx.StreamConsumed):
list(response.iter_raw())
# Assert a response can be streamed more than once
with client.stream(method="GET", url="https://test_url") as response:
assert list(response.iter_raw()) == []
# Assert that stream still behaves the proper way (can only be consumed once per request)
- with pytest.raises(httpx.StreamConsumed):
+ with pytest.raises(backend.httpx.StreamConsumed):
list(response.iter_raw())
-def test_with_many_responses(httpx_mock: HTTPXMock) -> None:
+def test_with_many_responses(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(url="https://test_url", content=b"test content 1")
httpx_mock.add_response(url="https://test_url", content=b"test content 2")
httpx_mock.add_response(url="https://test_url", content=b"test content 2")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.content == b"test content 1"
@@ -534,13 +571,15 @@ def test_with_many_responses(httpx_mock: HTTPXMock) -> None:
assert response.content == b"test content 2"
-def test_with_many_reused_responses(httpx_mock: HTTPXMock) -> None:
+def test_with_many_reused_responses(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url", content=b"test content 1")
httpx_mock.add_response(
url="https://test_url", content=b"test content 2", is_reusable=True
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.content == b"test content 1"
@@ -551,7 +590,9 @@ def test_with_many_reused_responses(httpx_mock: HTTPXMock) -> None:
assert response.content == b"test content 2"
-def test_with_many_responses_methods(httpx_mock: HTTPXMock) -> None:
+def test_with_many_responses_methods(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url", method="GET", content=b"test content 1"
)
@@ -571,7 +612,7 @@ def test_with_many_responses_methods(httpx_mock: HTTPXMock) -> None:
url="https://test_url", method="HEAD", content=b"test content 6"
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.post("https://test_url")
assert response.content == b"test content 2"
@@ -591,7 +632,9 @@ def test_with_many_responses_methods(httpx_mock: HTTPXMock) -> None:
assert response.content == b"test content 4"
-def test_with_many_responses_status_codes(httpx_mock: HTTPXMock) -> None:
+def test_with_many_responses_status_codes(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url", method="GET", content=b"test content 1", status_code=200
)
@@ -623,7 +666,7 @@ def test_with_many_responses_status_codes(httpx_mock: HTTPXMock) -> None:
status_code=500,
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.post("https://test_url")
assert response.content == b"test content 2"
assert response.status_code == 201
@@ -649,7 +692,9 @@ def test_with_many_responses_status_codes(httpx_mock: HTTPXMock) -> None:
assert response.status_code == 303
-def test_with_many_responses_urls_str(httpx_mock: HTTPXMock) -> None:
+def test_with_many_responses_urls_str(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url?param1=test", method="GET", content=b"test content 1"
)
@@ -669,35 +714,45 @@ def test_with_many_responses_urls_str(httpx_mock: HTTPXMock) -> None:
url="https://test_url?param6=test", method="HEAD", content=b"test content 6"
)
- with httpx.Client() as client:
- response = client.post(httpx.URL("https://test_url", params={"param2": "test"}))
+ with backend.httpx.Client() as client:
+ response = client.post(
+ backend.httpx.URL("https://test_url", params={"param2": "test"})
+ )
assert response.content == b"test content 2"
- response = client.get(httpx.URL("https://test_url", params={"param1": "test"}))
+ response = client.get(
+ backend.httpx.URL("https://test_url", params={"param1": "test"})
+ )
assert response.content == b"test content 1"
- response = client.put(httpx.URL("https://test_url", params={"param3": "test"}))
+ response = client.put(
+ backend.httpx.URL("https://test_url", params={"param3": "test"})
+ )
assert response.content == b"test content 3"
- response = client.head(httpx.URL("https://test_url", params={"param6": "test"}))
+ response = client.head(
+ backend.httpx.URL("https://test_url", params={"param6": "test"})
+ )
assert response.content == b"test content 6"
response = client.patch(
- httpx.URL("https://test_url", params={"param5": "test"})
+ backend.httpx.URL("https://test_url", params={"param5": "test"})
)
assert response.content == b"test content 5"
response = client.delete(
- httpx.URL("https://test_url", params={"param4": "test"})
+ backend.httpx.URL("https://test_url", params={"param4": "test"})
)
assert response.content == b"test content 4"
-def test_response_with_pattern_in_url(httpx_mock: HTTPXMock) -> None:
+def test_response_with_pattern_in_url(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url=re.compile(".*test.*"))
httpx_mock.add_response(url="https://unmatched", content=b"test content")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://unmatched")
assert response.content == b"test content"
@@ -705,11 +760,13 @@ def test_response_with_pattern_in_url(httpx_mock: HTTPXMock) -> None:
assert response.content == b""
-def test_request_with_pattern_in_url(httpx_mock: HTTPXMock) -> None:
+def test_request_with_pattern_in_url(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url")
httpx_mock.add_response(url="https://unmatched")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.get("https://unmatched")
client.get("https://test_url", headers={"X-Test": "1"})
@@ -718,12 +775,14 @@ def test_request_with_pattern_in_url(httpx_mock: HTTPXMock) -> None:
assert request.headers["x-test"] == "1"
-def test_requests_with_pattern_in_url(httpx_mock: HTTPXMock) -> None:
+def test_requests_with_pattern_in_url(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url")
httpx_mock.add_response(url="https://tests_url")
httpx_mock.add_response(url="https://unmatched")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.get("https://tests_url", headers={"X-Test": "1"})
client.get("https://unmatched", headers={"X-Test": "2"})
client.get("https://test_url")
@@ -734,12 +793,14 @@ def test_requests_with_pattern_in_url(httpx_mock: HTTPXMock) -> None:
assert "x-test" not in requests[1].headers
-def test_callback_with_pattern_in_url(httpx_mock: HTTPXMock) -> None:
- def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json={"url": str(request.url)})
+def test_callback_with_pattern_in_url(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+ def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json={"url": str(request.url)})
- def custom_response2(request: httpx.Request) -> httpx.Response:
- return httpx.Response(
+ def custom_response2(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(
status_code=200,
extensions={"http_version": b"HTTP/2.0"},
json={"url": str(request.url)},
@@ -748,7 +809,7 @@ def custom_response2(request: httpx.Request) -> httpx.Response:
httpx_mock.add_callback(custom_response, url=re.compile(".*test.*"))
httpx_mock.add_callback(custom_response2, url="https://unmatched")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://unmatched")
assert response.http_version == "HTTP/2.0"
@@ -756,39 +817,41 @@ def custom_response2(request: httpx.Request) -> httpx.Response:
assert response.http_version == "HTTP/1.1"
-def test_with_many_responses_urls_instances(httpx_mock: HTTPXMock) -> None:
+def test_with_many_responses_urls_instances(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
- url=httpx.URL("https://test_url", params={"param1": "test"}),
+ url=backend.httpx.URL("https://test_url", params={"param1": "test"}),
method="GET",
content=b"test content 1",
)
httpx_mock.add_response(
- url=httpx.URL("https://test_url", params={"param2": "test"}),
+ url=backend.httpx.URL("https://test_url", params={"param2": "test"}),
method="POST",
content=b"test content 2",
)
httpx_mock.add_response(
- url=httpx.URL("https://test_url", params={"param3": "test"}),
+ url=backend.httpx.URL("https://test_url", params={"param3": "test"}),
method="PUT",
content=b"test content 3",
)
httpx_mock.add_response(
- url=httpx.URL("https://test_url", params={"param4": "test"}),
+ url=backend.httpx.URL("https://test_url", params={"param4": "test"}),
method="DELETE",
content=b"test content 4",
)
httpx_mock.add_response(
- url=httpx.URL("https://test_url", params={"param5": "test"}),
+ url=backend.httpx.URL("https://test_url", params={"param5": "test"}),
method="PATCH",
content=b"test content 5",
)
httpx_mock.add_response(
- url=httpx.URL("https://test_url", params={"param6": "test"}),
+ url=backend.httpx.URL("https://test_url", params={"param6": "test"}),
method="HEAD",
content=b"test content 6",
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.post("https://test_url?param2=test")
assert response.content == b"test content 2"
@@ -808,33 +871,33 @@ def test_with_many_responses_urls_instances(httpx_mock: HTTPXMock) -> None:
assert response.content == b"test content 4"
-def test_with_http_version_2(httpx_mock: HTTPXMock) -> None:
+def test_with_http_version_2(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(
url="https://test_url", http_version="HTTP/2", content=b"test content 1"
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.content == b"test content 1"
assert response.http_version == "HTTP/2"
-def test_with_headers(httpx_mock: HTTPXMock) -> None:
+def test_with_headers(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(
url="https://test_url",
content=b"test content 1",
headers={"X-Test": "Test value"},
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.content == b"test content 1"
- assert response.headers == httpx.Headers(
+ assert response.headers == backend.httpx.Headers(
{"x-test": "Test value", "content-length": "14"}
)
-def test_requests_retrieval(httpx_mock: HTTPXMock) -> None:
+def test_requests_retrieval(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(
url="https://test_url", method="GET", content=b"test content 1"
)
@@ -854,7 +917,7 @@ def test_requests_retrieval(httpx_mock: HTTPXMock) -> None:
url="https://test_url", method="HEAD", content=b"test content 6"
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.post("https://test_url", content=b"sent content 2")
client.get("https://test_url", headers={"X-TEST": "test header 1"})
client.put("https://test_url", content=b"sent content 3")
@@ -863,71 +926,77 @@ def test_requests_retrieval(httpx_mock: HTTPXMock) -> None:
client.delete("https://test_url", headers={"X-Test": "test header 4"})
patch_request = httpx_mock.get_request(
- url=httpx.URL("https://test_url"), method="PATCH"
+ url=backend.httpx.URL("https://test_url"), method="PATCH"
)
assert patch_request is not None
assert patch_request.read() == b"sent content 5"
head_request = httpx_mock.get_request(
- url=httpx.URL("https://test_url"), method="HEAD"
+ url=backend.httpx.URL("https://test_url"), method="HEAD"
)
assert head_request is not None
assert head_request.read() == b""
put_request = httpx_mock.get_request(
- url=httpx.URL("https://test_url"), method="PUT"
+ url=backend.httpx.URL("https://test_url"), method="PUT"
)
assert put_request is not None
assert put_request.read() == b"sent content 3"
get_request = httpx_mock.get_request(
- url=httpx.URL("https://test_url"), method="GET"
+ url=backend.httpx.URL("https://test_url"), method="GET"
)
assert get_request is not None
assert get_request.headers["x-test"] == "test header 1"
post_request = httpx_mock.get_request(
- url=httpx.URL("https://test_url"), method="POST"
+ url=backend.httpx.URL("https://test_url"), method="POST"
)
assert post_request is not None
assert post_request.read() == b"sent content 2"
delete_request = httpx_mock.get_request(
- url=httpx.URL("https://test_url"), method="DELETE"
+ url=backend.httpx.URL("https://test_url"), method="DELETE"
)
assert delete_request is not None
assert delete_request.headers["x-test"] == "test header 4"
-def test_requests_retrieval_on_same_url(httpx_mock: HTTPXMock) -> None:
+def test_requests_retrieval_on_same_url(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url", is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.get("https://test_url", headers={"X-TEST": "test header 1"})
client.get("https://test_url", headers={"X-TEST": "test header 2"})
- requests = httpx_mock.get_requests(url=httpx.URL("https://test_url"))
+ requests = httpx_mock.get_requests(url=backend.httpx.URL("https://test_url"))
assert len(requests) == 2
assert requests[0].headers["x-test"] == "test header 1"
assert requests[1].headers["x-test"] == "test header 2"
-def test_request_retrieval_on_same_url(httpx_mock: HTTPXMock) -> None:
+def test_request_retrieval_on_same_url(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.get("https://test_url", headers={"X-TEST": "test header 1"})
client.get("https://test_url2", headers={"X-TEST": "test header 2"})
- request = httpx_mock.get_request(url=httpx.URL("https://test_url"))
+ request = httpx_mock.get_request(url=backend.httpx.URL("https://test_url"))
assert request is not None
assert request.headers["x-test"] == "test header 1"
-def test_requests_retrieval_on_same_method(httpx_mock: HTTPXMock) -> None:
+def test_requests_retrieval_on_same_method(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.get("https://test_url", headers={"X-TEST": "test header 1"})
client.get("https://test_url2", headers={"X-TEST": "test header 2"})
@@ -937,10 +1006,12 @@ def test_requests_retrieval_on_same_method(httpx_mock: HTTPXMock) -> None:
assert requests[1].headers["x-test"] == "test header 2"
-def test_request_retrieval_on_same_method(httpx_mock: HTTPXMock) -> None:
+def test_request_retrieval_on_same_method(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.get("https://test_url", headers={"X-TEST": "test header 1"})
client.post("https://test_url", headers={"X-TEST": "test header 2"})
@@ -949,25 +1020,31 @@ def test_request_retrieval_on_same_method(httpx_mock: HTTPXMock) -> None:
assert request.headers["x-test"] == "test header 1"
-def test_requests_retrieval_on_same_url_and_method(httpx_mock: HTTPXMock) -> None:
+def test_requests_retrieval_on_same_url_and_method(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.get("https://test_url", headers={"X-TEST": "test header 1"})
client.get("https://test_url", headers={"X-TEST": "test header 2"})
client.post("https://test_url", headers={"X-TEST": "test header 3"})
client.get("https://test_url2", headers={"X-TEST": "test header 4"})
- requests = httpx_mock.get_requests(url=httpx.URL("https://test_url"), method="GET")
+ requests = httpx_mock.get_requests(
+ url=backend.httpx.URL("https://test_url"), method="GET"
+ )
assert len(requests) == 2
assert requests[0].headers["x-test"] == "test header 1"
assert requests[1].headers["x-test"] == "test header 2"
-def test_default_requests_retrieval(httpx_mock: HTTPXMock) -> None:
+def test_default_requests_retrieval(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.post("https://test_url", headers={"X-TEST": "test header 1"})
client.get("https://test_url2", headers={"X-TEST": "test header 2"})
@@ -977,10 +1054,12 @@ def test_default_requests_retrieval(httpx_mock: HTTPXMock) -> None:
assert requests[1].headers["x-test"] == "test header 2"
-def test_default_request_retrieval(httpx_mock: HTTPXMock) -> None:
+def test_default_request_retrieval(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response()
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.post("https://test_url", headers={"X-TEST": "test header 1"})
request = httpx_mock.get_request()
@@ -988,7 +1067,7 @@ def test_default_request_retrieval(httpx_mock: HTTPXMock) -> None:
assert request.headers["x-test"] == "test header 1"
-def test_requests_json_body(httpx_mock: HTTPXMock) -> None:
+def test_requests_json_body(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(
url="https://test_url", method="GET", json=["list content 1", "list content 2"]
)
@@ -999,7 +1078,7 @@ def test_requests_json_body(httpx_mock: HTTPXMock) -> None:
)
httpx_mock.add_response(url="https://test_url", method="PUT", json="string value")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.post("https://test_url")
assert response.json() == {"key 1": "value 1", "key 2": "value 2"}
assert response.headers["content-type"] == "application/json"
@@ -1013,51 +1092,59 @@ def test_requests_json_body(httpx_mock: HTTPXMock) -> None:
assert response.headers["content-type"] == "application/json"
-def test_callback_raising_exception(httpx_mock: HTTPXMock) -> None:
- def raise_timeout(request: httpx.Request) -> httpx.Response:
- raise httpx.ReadTimeout(
+def test_callback_raising_exception(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+ def raise_timeout(request: "httpx.Request") -> "httpx.Response":
+ raise backend.httpx.ReadTimeout(
f"Unable to read within {request.extensions['timeout']['read']}",
request=request,
)
httpx_mock.add_callback(raise_timeout, url="https://test_url")
- with httpx.Client() as client:
- with pytest.raises(httpx.ReadTimeout) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.ReadTimeout) as exception_info:
client.get("https://test_url")
assert str(exception_info.value) == "Unable to read within 5.0"
-def test_request_exception_raising(httpx_mock: HTTPXMock) -> None:
+def test_request_exception_raising(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_exception(
- httpx.ReadTimeout("Unable to read within 5.0"), url="https://test_url"
+ backend.httpx.ReadTimeout("Unable to read within 5.0"), url="https://test_url"
)
- with httpx.Client() as client:
- with pytest.raises(httpx.ReadTimeout) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.ReadTimeout) as exception_info:
client.get("https://test_url")
assert str(exception_info.value) == "Unable to read within 5.0"
assert exception_info.value.request is not None
-def test_non_request_exception_raising(httpx_mock: HTTPXMock) -> None:
+def test_non_request_exception_raising(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_exception(
- httpx.HTTPError("Unable to read within 5.0"), url="https://test_url"
+ backend.httpx.HTTPError("Unable to read within 5.0"), url="https://test_url"
)
- with httpx.Client() as client:
- with pytest.raises(httpx.HTTPError) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.HTTPError) as exception_info:
client.get("https://test_url")
assert str(exception_info.value) == "Unable to read within 5.0"
-def test_callback_returning_response(httpx_mock: HTTPXMock) -> None:
- def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json={"url": str(request.url)})
+def test_callback_returning_response(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+ def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json={"url": str(request.url)})
httpx_mock.add_callback(custom_response, url="https://test_url")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.json() == {"url": "https://test_url"}
assert response.headers["content-type"] == "application/json"
@@ -1066,26 +1153,26 @@ def custom_response(request: httpx.Request) -> httpx.Response:
@pytest.mark.parametrize("return_value", [None, "not a response"])
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_callback_not_returning_a_response(
- httpx_mock: HTTPXMock, return_value: str | None
+ httpx_mock: HTTPXMock, return_value: str | None, backend: HTTPXBackend
) -> None:
httpx_mock.add_callback(lambda request: return_value, url="https://test_url")
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.get("https://test_url")
assert (
str(exception_info.value)
- == "Callback registered for GET request on https://test_url MUST return httpx.Response"
+ == f"Callback registered for GET request on https://test_url MUST return {backend.name}.Response"
)
-def test_callback_executed_twice(httpx_mock: HTTPXMock) -> None:
- def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json=["content"])
+def test_callback_executed_twice(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
+ def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json=["content"])
httpx_mock.add_callback(custom_response, is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.json() == ["content"]
assert response.headers["content-type"] == "application/json"
@@ -1095,14 +1182,16 @@ def custom_response(request: httpx.Request) -> httpx.Response:
assert response.headers["content-type"] == "application/json"
-def test_callback_registered_after_response(httpx_mock: HTTPXMock) -> None:
- def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json=["content2"])
+def test_callback_registered_after_response(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+ def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json=["content2"])
httpx_mock.add_response(json=["content1"])
httpx_mock.add_callback(custom_response, is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.json() == ["content1"]
assert response.headers["content-type"] == "application/json"
@@ -1117,14 +1206,16 @@ def custom_response(request: httpx.Request) -> httpx.Response:
assert response.headers["content-type"] == "application/json"
-def test_response_registered_after_callback(httpx_mock: HTTPXMock) -> None:
- def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json=["content1"])
+def test_response_registered_after_callback(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
+ def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json=["content1"])
httpx_mock.add_callback(custom_response)
httpx_mock.add_response(json=["content2"], is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.json() == ["content1"]
assert response.headers["content-type"] == "application/json"
@@ -1139,13 +1230,13 @@ def custom_response(request: httpx.Request) -> httpx.Response:
assert response.headers["content-type"] == "application/json"
-def test_callback_matching_method(httpx_mock: HTTPXMock) -> None:
- def custom_response(request: httpx.Request) -> httpx.Response:
- return httpx.Response(status_code=200, json=["content"])
+def test_callback_matching_method(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
+ def custom_response(request: "httpx.Request") -> "httpx.Response":
+ return backend.httpx.Response(status_code=200, json=["content"])
httpx_mock.add_callback(custom_response, method="GET", is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.json() == ["content"]
assert response.headers["content-type"] == "application/json"
@@ -1159,21 +1250,26 @@ def test_request_retrieval_with_more_than_one(testdir: Testdir) -> None:
"""
Single request cannot be returned if there is more than one matching.
"""
+ testdir.makeconftest("""
+ import pytest
+ from pytest_httpx import HTTPXBackend, get_backends
+
+ @pytest.fixture(params=get_backends(), ids=lambda b: b.name)
+ def backend(request):
+ return request.param
+ """)
testdir.makepyfile("""
- import httpx
-
-
- def test_request_retrieval_with_more_than_one(httpx_mock):
+ def test_request_retrieval_with_more_than_one(httpx_mock, backend):
httpx_mock.add_response(is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.get("https://test_url", headers={"X-TEST": "test header 1"})
client.get("https://test_url", headers={"X-TEST": "test header 2"})
- httpx_mock.get_request(url=httpx.URL("https://test_url"))
+ httpx_mock.get_request(url=backend.httpx.URL("https://test_url"))
""")
result = testdir.runpytest()
- result.assert_outcomes(failed=1)
+ result.assert_outcomes(failed=len(get_backends()))
result.stdout.fnmatch_lines(
[
"*AssertionError: More than one request (2) matched, use get_requests instead or refine your filters."
@@ -1181,20 +1277,24 @@ def test_request_retrieval_with_more_than_one(httpx_mock):
)
-def test_headers_matching(httpx_mock: HTTPXMock) -> None:
+def test_headers_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(
- match_headers={"User-Agent": f"python-httpx/{httpx.__version__}"}
+ match_headers={
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}"
+ }
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.content == b""
-def test_multi_value_headers_matching(httpx_mock: HTTPXMock) -> None:
+def test_multi_value_headers_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(match_headers={"my-custom-header": "value1, value2"})
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get(
"https://test_url",
headers=[("my-custom-header", "value1"), ("my-custom-header", "value2")],
@@ -1205,13 +1305,14 @@ def test_multi_value_headers_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_multi_value_headers_not_matching_single_value_issued(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
match_headers={"my-custom-header": "value1"}, is_optional=True
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.get(
"https://test_url",
headers=[
@@ -1229,13 +1330,14 @@ def test_multi_value_headers_not_matching_single_value_issued(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_multi_value_headers_not_matching_multi_value_issued(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
match_headers={"my-custom-header": "value1, value2"}, is_optional=True
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.get(
"https://test_url",
headers=[
@@ -1251,64 +1353,74 @@ def test_multi_value_headers_not_matching_multi_value_issued(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_headers_matching_respect_case(httpx_mock: HTTPXMock) -> None:
+def test_headers_matching_respect_case(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
- match_headers={"user-agent": f"python-httpx/{httpx.__version__}"},
+ match_headers={
+ "user-agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}"
+ },
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.get("https://test_url")
assert (
str(exception_info.value)
- == f"""No response can be found for GET request on https://test_url with {{'User-Agent': 'python-httpx/{httpx.__version__}'}} headers amongst:
-- Match any request with {{'user-agent': 'python-httpx/{httpx.__version__}'}} headers"""
+ == f"""No response can be found for GET request on https://test_url with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers amongst:
+- Match any request with {{'user-agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers"""
)
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_headers_not_matching(httpx_mock: HTTPXMock) -> None:
+def test_headers_not_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
"Host2": "test_url",
},
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.get("https://test_url")
assert (
str(exception_info.value)
- == f"""No response can be found for GET request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers amongst:
-- Match any request with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2', 'Host2': 'test_url'}} headers"""
+ == f"""No response can be found for GET request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers amongst:
+- Match any request with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2', 'Host2': 'test_url'}} headers"""
)
-def test_content_matching(httpx_mock: HTTPXMock) -> None:
+def test_content_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(match_content=b"This is the body")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.post("https://test_url", content=b"This is the body")
assert response.read() == b""
-def test_proxy_matching_with_authentication(httpx_mock: HTTPXMock) -> None:
+def test_proxy_matching_with_authentication(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(proxy_url="http://user:pwd@my_other_proxy/")
- with httpx.Client(proxy="http://user:pwd@my_other_proxy") as client:
+ with backend.httpx.Client(proxy="http://user:pwd@my_other_proxy") as client:
response = client.get("https://test_url")
assert response.read() == b""
-def test_proxy_matching_with_custom_proxy_headers(httpx_mock: HTTPXMock) -> None:
+def test_proxy_matching_with_custom_proxy_headers(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(proxy_url="http://my_test_proxy/")
- with httpx.Client(
- proxy=httpx.Proxy("http://my_test_proxy", headers={"X-Something": "value"})
+ with backend.httpx.Client(
+ proxy=backend.httpx.Proxy(
+ "http://my_test_proxy", headers={"X-Something": "value"}
+ )
) as client:
response = client.get("https://test_url")
assert response.read() == b""
@@ -1316,11 +1428,12 @@ def test_proxy_matching_with_custom_proxy_headers(httpx_mock: HTTPXMock) -> None
def test_proxy_matching_with_authentication_and_custom_proxy_headers(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(proxy_url="http://user:pwd@my_other_proxy/")
- with httpx.Client(
- proxy=httpx.Proxy(
+ with backend.httpx.Client(
+ proxy=backend.httpx.Proxy(
"http://user:pwd@my_other_proxy", headers={"X-Something": "value"}
)
) as client:
@@ -1329,11 +1442,11 @@ def test_proxy_matching_with_authentication_and_custom_proxy_headers(
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_proxy_not_matching(httpx_mock: HTTPXMock) -> None:
+def test_proxy_not_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(proxy_url="http://my_test_proxy", is_optional=True)
- with httpx.Client(proxy="http://my_test_proxy") as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client(proxy="http://my_test_proxy") as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.get("http://test_url")
assert (
str(exception_info.value)
@@ -1343,11 +1456,11 @@ def test_proxy_not_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_proxy_not_existing(httpx_mock: HTTPXMock) -> None:
+def test_proxy_not_existing(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(proxy_url="http://my_test_proxy", is_optional=True)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.get("http://test_url")
assert (
str(exception_info.value)
@@ -1356,10 +1469,12 @@ def test_proxy_not_existing(httpx_mock: HTTPXMock) -> None:
)
-def test_requests_retrieval_content_matching(httpx_mock: HTTPXMock) -> None:
+def test_requests_retrieval_content_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.post("https://test_url", content=b"This is the body")
client.post("https://test_url2", content=b"This is the body")
client.post("https://test_url2", content=b"This is the body2")
@@ -1367,10 +1482,12 @@ def test_requests_retrieval_content_matching(httpx_mock: HTTPXMock) -> None:
assert len(httpx_mock.get_requests(match_content=b"This is the body")) == 2
-def test_requests_retrieval_json_matching(httpx_mock: HTTPXMock) -> None:
+def test_requests_retrieval_json_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.post("https://test_url", json=["my_str"])
client.post("https://test_url2", json=["my_str"])
client.post("https://test_url2", json=["my_str2"])
@@ -1378,13 +1495,17 @@ def test_requests_retrieval_json_matching(httpx_mock: HTTPXMock) -> None:
assert len(httpx_mock.get_requests(match_json=["my_str"])) == 2
-def test_requests_retrieval_proxy_matching(httpx_mock: HTTPXMock) -> None:
+def test_requests_retrieval_proxy_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- with httpx.Client(
+ with backend.httpx.Client(
mounts={
- "http://": httpx.HTTPTransport(proxy="http://my_test_proxy"),
- "https://": httpx.HTTPTransport(proxy="http://user:pwd@my_other_proxy"),
+ "http://": backend.httpx.HTTPTransport(proxy="http://my_test_proxy"),
+ "https://": backend.httpx.HTTPTransport(
+ proxy="http://user:pwd@my_other_proxy"
+ ),
}
) as client:
client.get("https://test_url")
@@ -1396,13 +1517,17 @@ def test_requests_retrieval_proxy_matching(httpx_mock: HTTPXMock) -> None:
)
-def test_request_retrieval_proxy_matching(httpx_mock: HTTPXMock) -> None:
+def test_request_retrieval_proxy_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- with httpx.Client(
+ with backend.httpx.Client(
mounts={
- "http://": httpx.HTTPTransport(proxy="http://my_test_proxy"),
- "https://": httpx.HTTPTransport(proxy="http://user:pwd@my_other_proxy"),
+ "http://": backend.httpx.HTTPTransport(proxy="http://my_test_proxy"),
+ "https://": backend.httpx.HTTPTransport(
+ proxy="http://user:pwd@my_other_proxy"
+ ),
}
) as client:
client.get("https://test_url")
@@ -1412,10 +1537,12 @@ def test_request_retrieval_proxy_matching(httpx_mock: HTTPXMock) -> None:
assert httpx_mock.get_request(proxy_url="http://my_test_proxy/")
-def test_requests_retrieval_files_and_data_matching(httpx_mock: HTTPXMock) -> None:
+def test_requests_retrieval_files_and_data_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.put(
"https://test_url",
files={"name": ("file_name", b"File content")},
@@ -1443,10 +1570,12 @@ def test_requests_retrieval_files_and_data_matching(httpx_mock: HTTPXMock) -> No
)
-def test_request_retrieval_files_and_data_matching(httpx_mock: HTTPXMock) -> None:
+def test_request_retrieval_files_and_data_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.put(
"https://test_url",
files={"name": ("file_name", b"File content")},
@@ -1461,10 +1590,12 @@ def test_request_retrieval_files_and_data_matching(httpx_mock: HTTPXMock) -> Non
)
-def test_requests_retrieval_extensions_matching(httpx_mock: HTTPXMock) -> None:
+def test_requests_retrieval_extensions_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.get("https://test_url")
client.get("https://test_url2", timeout=10)
client.get("https://test_url2", timeout=10)
@@ -1480,11 +1611,13 @@ def test_requests_retrieval_extensions_matching(httpx_mock: HTTPXMock) -> None:
)
-def test_request_retrieval_extensions_matching(httpx_mock: HTTPXMock) -> None:
+def test_request_retrieval_extensions_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(is_reusable=True)
- with httpx.Client() as client:
- client.get("https://test_url", timeout=httpx.Timeout(5, read=10))
+ with backend.httpx.Client() as client:
+ client.get("https://test_url", timeout=backend.httpx.Timeout(5, read=10))
client.get("https://test_url2", timeout=10)
client.get("http://test_url2", timeout=10)
@@ -1494,11 +1627,11 @@ def test_request_retrieval_extensions_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_content_not_matching(httpx_mock: HTTPXMock) -> None:
+def test_content_not_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(match_content=b"This is the body", is_optional=True)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body2")
assert (
str(exception_info.value)
@@ -1542,28 +1675,28 @@ def test_match_content_and_match_files_error(httpx_mock: HTTPXMock) -> None:
)
-def test_json_matching(httpx_mock: HTTPXMock) -> None:
+def test_json_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(match_json={"a": 1, "b": 2})
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.post("https://test_url", json={"b": 2, "a": 1})
assert response.read() == b""
-def test_json_partial_matching(httpx_mock: HTTPXMock) -> None:
+def test_json_partial_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(match_json={"a": 1, "b": ANY})
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.post("https://test_url", json={"b": 2, "a": 1})
assert response.read() == b""
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_json_not_matching(httpx_mock: HTTPXMock) -> None:
+def test_json_not_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(match_json={"a": 1, "b": 2}, is_optional=True)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", json={"c": 3, "b": 2, "a": 1})
assert (
str(exception_info.value)
@@ -1573,15 +1706,17 @@ def test_json_not_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_headers_and_json_not_matching(httpx_mock: HTTPXMock) -> None:
+def test_headers_and_json_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
match_json={"a": 1, "b": 2},
match_headers={"foo": "bar"},
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", json={"c": 3, "b": 2, "a": 1})
assert (
str(exception_info.value)
@@ -1591,11 +1726,11 @@ def test_headers_and_json_not_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_match_json_invalid_json(httpx_mock: HTTPXMock) -> None:
+def test_match_json_invalid_json(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(match_json={"a": 1, "b": 2}, is_optional=True)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"foobar")
assert (
str(exception_info.value)
@@ -1606,11 +1741,13 @@ def test_match_json_invalid_json(httpx_mock: HTTPXMock) -> None:
@pytest.mark.parametrize("content", [b'{"a":"\xff"}', b'{"a":"\xc3"}'])
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_match_json_invalid_utf8(httpx_mock: HTTPXMock, content: bytes) -> None:
+def test_match_json_invalid_utf8(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend, content: bytes
+) -> None:
httpx_mock.add_response(match_json={"a": "value"})
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=content)
assert exception_info.value.request.content == content
assert "No response can be found" in str(exception_info.value)
@@ -1619,11 +1756,13 @@ def test_match_json_invalid_utf8(httpx_mock: HTTPXMock, content: bytes) -> None:
assert response.status_code == 200
-def test_match_json_binary_content_fallback(httpx_mock: HTTPXMock) -> None:
+def test_match_json_binary_content_fallback(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(match_json={"a": "value"}, status_code=201)
httpx_mock.add_response(match_content=b"\xff", status_code=202)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.post("https://test_url", content=b"\xff")
assert response.status_code == 202
response = client.post("https://test_url", json={"a": "value"})
@@ -1631,11 +1770,11 @@ def test_match_json_binary_content_fallback(httpx_mock: HTTPXMock) -> None:
def test_requests_retrieval_json_matching_with_binary_content(
- httpx_mock: HTTPXMock,
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
) -> None:
httpx_mock.add_response(is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
binary_request = client.post("https://test_url", content=b"\xff").request
json_request = client.post("https://test_url", json={"a": "value"}).request
@@ -1644,88 +1783,102 @@ def test_requests_retrieval_json_matching_with_binary_content(
assert httpx_mock.get_request(match_content=b"\xff") is binary_request
-def test_headers_and_content_matching(httpx_mock: HTTPXMock) -> None:
+def test_headers_and_content_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
- match_headers={"User-Agent": f"python-httpx/{httpx.__version__}"},
+ match_headers={
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}"
+ },
match_content=b"This is the body",
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.post("https://test_url", content=b"This is the body")
assert response.content == b""
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_headers_not_matching_and_content_matching(httpx_mock: HTTPXMock) -> None:
+def test_headers_not_matching_and_content_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body",
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
)
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_headers_matching_and_content_not_matching(httpx_mock: HTTPXMock) -> None:
+def test_headers_matching_and_content_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url",
},
match_content=b"This is the body2",
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
)
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_headers_and_content_not_matching(httpx_mock: HTTPXMock) -> None:
+def test_headers_and_content_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body2",
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
)
-def test_url_and_headers_and_content_matching(httpx_mock: HTTPXMock) -> None:
+def test_url_and_headers_and_content_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url",
- match_headers={"User-Agent": f"python-httpx/{httpx.__version__}"},
+ match_headers={
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}"
+ },
match_content=b"This is the body",
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.post("https://test_url", content=b"This is the body")
assert response.content == b""
@@ -1733,154 +1886,165 @@ def test_url_and_headers_and_content_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_headers_not_matching_and_url_and_content_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body",
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request on https://test_url with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request on https://test_url with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
)
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_url_and_headers_not_matching_and_content_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url2",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body",
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request on https://test_url2 with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request on https://test_url2 with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
)
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_url_and_headers_matching_and_content_not_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url",
},
match_content=b"This is the body2",
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request on https://test_url with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request on https://test_url with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
)
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_headers_matching_and_url_and_content_not_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url2",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url",
},
match_content=b"This is the body2",
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request on https://test_url2 with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request on https://test_url2 with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
)
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_url_matching_and_headers_and_content_not_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body2",
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request on https://test_url with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request on https://test_url with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
)
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_url_and_headers_and_content_not_matching(httpx_mock: HTTPXMock) -> None:
+def test_url_and_headers_and_content_not_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url2",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body2",
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match any request on https://test_url2 with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match any request on https://test_url2 with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
)
-def test_method_and_url_and_headers_and_content_matching(httpx_mock: HTTPXMock) -> None:
+def test_method_and_url_and_headers_and_content_matching(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
url="https://test_url",
method="POST",
- match_headers={"User-Agent": f"python-httpx/{httpx.__version__}"},
+ match_headers={
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}"
+ },
match_content=b"This is the body",
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.post("https://test_url", content=b"This is the body")
assert response.content == b""
@@ -1888,255 +2052,274 @@ def test_method_and_url_and_headers_and_content_matching(httpx_mock: HTTPXMock)
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_headers_not_matching_and_method_and_url_and_content_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url",
method="POST",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body",
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match POST request on https://test_url with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match POST request on https://test_url with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
)
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_url_and_headers_not_matching_and_method_and_content_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url2",
method="POST",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body",
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match POST request on https://test_url2 with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match POST request on https://test_url2 with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body' body"""
)
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_method_and_url_and_headers_matching_and_content_not_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url",
method="POST",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url",
},
match_content=b"This is the body2",
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match POST request on https://test_url with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match POST request on https://test_url with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
)
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_method_and_headers_matching_and_url_and_content_not_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url2",
method="POST",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url",
},
match_content=b"This is the body2",
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match POST request on https://test_url2 with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match POST request on https://test_url2 with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url'}} headers and b'This is the body2' body"""
)
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_method_and_url_matching_and_headers_and_content_not_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url",
method="POST",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body2",
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match POST request on https://test_url with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match POST request on https://test_url with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
)
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_method_matching_and_url_and_headers_and_content_not_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url2",
method="POST",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body2",
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match POST request on https://test_url2 with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match POST request on https://test_url2 with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
)
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_method_and_url_and_headers_and_content_not_matching(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(
url="https://test_url2",
method="PUT",
match_headers={
- "User-Agent": f"python-httpx/{httpx.__version__}",
+ "User-Agent": f"python-{backend.httpx.__name__}/{backend.httpx.__version__}",
"Host": "test_url2",
},
match_content=b"This is the body2",
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.post("https://test_url", content=b"This is the body")
assert (
str(exception_info.value)
- == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-httpx/{httpx.__version__}'}} headers and b'This is the body' body amongst:
-- Match PUT request on https://test_url2 with {{'User-Agent': 'python-httpx/{httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
+ == f"""No response can be found for POST request on https://test_url with {{'Host': 'test_url', 'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}'}} headers and b'This is the body' body amongst:
+- Match PUT request on https://test_url2 with {{'User-Agent': 'python-{backend.httpx.__name__}/{backend.httpx.__version__}', 'Host': 'test_url2'}} headers and b'This is the body2' body"""
)
-def test_header_as_str_tuple_list(httpx_mock: HTTPXMock) -> None:
+def test_header_as_str_tuple_list(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(
headers=[("set-cookie", "key=value"), ("set-cookie", "key2=value2")]
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert dict(response.cookies) == {"key": "value", "key2": "value2"}
-def test_header_as_bytes_tuple_list(httpx_mock: HTTPXMock) -> None:
+def test_header_as_bytes_tuple_list(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(
headers=[(b"set-cookie", b"key=value"), (b"set-cookie", b"key2=value2")]
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert dict(response.cookies) == {"key": "value", "key2": "value2"}
-def test_header_as_bytes_dict(httpx_mock: HTTPXMock) -> None:
+def test_header_as_bytes_dict(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(headers={b"set-cookie": b"key=value"})
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert dict(response.cookies) == {"key": "value"}
-def test_header_as_httpx_headers(httpx_mock: HTTPXMock) -> None:
- httpx_mock.add_response(headers=httpx.Headers({"set-cookie": "key=value"}))
+def test_header_as_httpx_headers(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
+ httpx_mock.add_response(headers=backend.httpx.Headers({"set-cookie": "key=value"}))
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert dict(response.cookies) == {"key": "value"}
-def test_elapsed_when_add_response(httpx_mock: HTTPXMock) -> None:
+def test_elapsed_when_add_response(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response()
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.elapsed is not None
-def test_elapsed_when_add_callback(httpx_mock: HTTPXMock) -> None:
+def test_elapsed_when_add_callback(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_callback(
- callback=lambda req: httpx.Response(status_code=200, json={"foo": "bar"})
+ callback=lambda req: backend.httpx.Response(
+ status_code=200, json={"foo": "bar"}
+ )
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.elapsed is not None
-def test_non_ascii_url_response(httpx_mock: HTTPXMock) -> None:
+def test_non_ascii_url_response(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(url="https://test_url?query_type=数据")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url?query_type=数据")
assert response.content == b""
-def test_url_encoded_matching_response(httpx_mock: HTTPXMock) -> None:
+def test_url_encoded_matching_response(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url?a=%E6%95%B0%E6%8D%AE")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url?a=数据")
assert response.content == b""
-def test_reset_is_removing_requests(httpx_mock: HTTPXMock) -> None:
+def test_reset_is_removing_requests(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response()
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.get("https://test_url")
assert len(httpx_mock.get_requests()) == 1
@@ -2145,14 +2328,14 @@ def test_reset_is_removing_requests(httpx_mock: HTTPXMock) -> None:
assert len(httpx_mock.get_requests()) == 0
-def test_mutating_json(httpx_mock: HTTPXMock) -> None:
+def test_mutating_json(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
mutating_json = {"content": "request 1"}
httpx_mock.add_response(json=mutating_json)
mutating_json["content"] = "request 2"
httpx_mock.add_response(json=mutating_json)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.json() == {"content": "request 1"}
@@ -2160,23 +2343,23 @@ def test_mutating_json(httpx_mock: HTTPXMock) -> None:
assert response.json() == {"content": "request 2"}
-def test_custom_transport(httpx_mock: HTTPXMock) -> None:
- class CustomTransport(httpx.HTTPTransport):
+def test_custom_transport(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
+ class CustomTransport(backend.httpx.HTTPTransport): # type: ignore[name-defined]
def __init__(self, prefix: str, *args, **kwargs):
super().__init__(*args, **kwargs)
self.prefix = prefix
def handle_request(
self,
- request: httpx.Request,
- ) -> httpx.Response:
+ request: "httpx.Request",
+ ) -> "httpx.Response":
httpx_response = super().handle_request(request)
httpx_response.headers["x-prefix"] = self.prefix
return httpx_response
httpx_mock.add_response()
- with httpx.Client(transport=CustomTransport(prefix="test")) as client:
+ with backend.httpx.Client(transport=CustomTransport(prefix="test")) as client:
response = client.post("https://test_url", content=b"This is the body")
assert response.read() == b""
assert response.headers["x-prefix"] == "test"
@@ -2184,6 +2367,7 @@ def handle_request(
def test_response_selection_content_matching_with_iterable(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(match_content=b"full content 1", content=b"matched 1")
httpx_mock.add_response(match_content=b"full content 2", content=b"matched 2")
@@ -2200,7 +2384,7 @@ def stream_content_2() -> Iterable[bytes]:
yield b"content"
yield b" 2"
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response_2 = client.put("https://test_url", content=stream_content_2())
response_1 = client.put("https://test_url", content=stream_content_1())
assert response_1.content == b"matched 1"
@@ -2209,6 +2393,7 @@ def stream_content_2() -> Iterable[bytes]:
def test_request_selection_content_matching_with_iterable(
httpx_mock: HTTPXMock,
+ backend: HTTPXBackend,
) -> None:
httpx_mock.add_response(match_content=b"full content 1")
httpx_mock.add_response(match_content=b"full content 2")
@@ -2225,7 +2410,7 @@ def stream_content_2() -> Iterable[bytes]:
yield b"content"
yield b" 2"
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.put("https://test_url_2", content=stream_content_2())
client.put("https://test_url_1", content=stream_content_1())
@@ -2238,23 +2423,23 @@ def stream_content_2() -> Iterable[bytes]:
assert request2.url == "https://test_url_2"
-def test_files_matching(httpx_mock: HTTPXMock) -> None:
+def test_files_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(match_files={"name": ("file_name", b"File content")})
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.put(
"https://test_url", files={"name": ("file_name", b"File content")}
)
assert response.content == b""
-def test_files_and_data_matching(httpx_mock: HTTPXMock) -> None:
+def test_files_and_data_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(
match_files={"name": ("file_name", b"File content")},
match_data={"field": "value"},
)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.put(
"https://test_url",
files={"name": ("file_name", b"File content")},
@@ -2264,7 +2449,9 @@ def test_files_and_data_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_files_not_matching_name(httpx_mock: HTTPXMock, monkeypatch) -> None:
+def test_files_not_matching_name(
+ httpx_mock: HTTPXMock, monkeypatch, backend: HTTPXBackend
+) -> None:
# Ensure generated boundary will be fbe495efe4cd41b941ca13e254d6b018
monkeypatch.setattr(
os,
@@ -2276,8 +2463,8 @@ def test_files_not_matching_name(httpx_mock: HTTPXMock, monkeypatch) -> None:
match_files={"name2": ("file_name", b"File content")}, is_optional=True
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.put(
"https://test_url", files={"name1": ("file_name", b"File content")}
)
@@ -2289,7 +2476,9 @@ def test_files_not_matching_name(httpx_mock: HTTPXMock, monkeypatch) -> None:
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_files_not_matching_file_name(httpx_mock: HTTPXMock, monkeypatch) -> None:
+def test_files_not_matching_file_name(
+ httpx_mock: HTTPXMock, monkeypatch, backend: HTTPXBackend
+) -> None:
# Ensure generated boundary will be fbe495efe4cd41b941ca13e254d6b018
monkeypatch.setattr(
os,
@@ -2301,8 +2490,8 @@ def test_files_not_matching_file_name(httpx_mock: HTTPXMock, monkeypatch) -> Non
match_files={"name": ("file_name2", b"File content")}, is_optional=True
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.put(
"https://test_url", files={"name": ("file_name1", b"File content")}
)
@@ -2314,7 +2503,9 @@ def test_files_not_matching_file_name(httpx_mock: HTTPXMock, monkeypatch) -> Non
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_files_not_matching_content(httpx_mock: HTTPXMock, monkeypatch) -> None:
+def test_files_not_matching_content(
+ httpx_mock: HTTPXMock, monkeypatch, backend: HTTPXBackend
+) -> None:
# Ensure generated boundary will be fbe495efe4cd41b941ca13e254d6b018
monkeypatch.setattr(
os,
@@ -2326,8 +2517,8 @@ def test_files_not_matching_content(httpx_mock: HTTPXMock, monkeypatch) -> None:
match_files={"name": ("file_name", b"File content2")}, is_optional=True
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.put(
"https://test_url", files={"name": ("file_name", b"File content1")}
)
@@ -2340,7 +2531,7 @@ def test_files_not_matching_content(httpx_mock: HTTPXMock, monkeypatch) -> None:
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
def test_files_matching_but_data_not_matching(
- httpx_mock: HTTPXMock, monkeypatch
+ httpx_mock: HTTPXMock, monkeypatch, backend: HTTPXBackend
) -> None:
# Ensure generated boundary will be fbe495efe4cd41b941ca13e254d6b018
monkeypatch.setattr(
@@ -2355,8 +2546,8 @@ def test_files_matching_but_data_not_matching(
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.put(
"https://test_url", files={"name": ("file_name", b"File content")}
)
@@ -2377,25 +2568,27 @@ def test_data_without_files(httpx_mock: HTTPXMock) -> None:
)
-def test_timeout_matching(httpx_mock: HTTPXMock) -> None:
+def test_timeout_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(
match_extensions={"timeout": {"connect": 5, "read": 5, "write": 10, "pool": 5}}
)
- with httpx.Client() as client:
- response = client.put("https://test_url", timeout=httpx.Timeout(5, write=10))
+ with backend.httpx.Client() as client:
+ response = client.put(
+ "https://test_url", timeout=backend.httpx.Timeout(5, write=10)
+ )
assert response.content == b""
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_timeout_not_matching(httpx_mock: HTTPXMock) -> None:
+def test_timeout_not_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(
match_extensions={"timeout": {"connect": 5, "read": 5, "write": 10, "pool": 5}},
is_optional=True,
)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.get("https://test_url", extensions={"test": "value"})
assert (
str(exception_info.value)
@@ -2404,10 +2597,10 @@ def test_timeout_not_matching(httpx_mock: HTTPXMock) -> None:
)
-def test_extensions_matching(httpx_mock: HTTPXMock) -> None:
+def test_extensions_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(match_extensions={"test": "value"})
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.put(
"https://test_url", extensions={"test": "value", "test2": "value2"}
)
@@ -2415,11 +2608,11 @@ def test_extensions_matching(httpx_mock: HTTPXMock) -> None:
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
-def test_extensions_not_matching(httpx_mock: HTTPXMock) -> None:
+def test_extensions_not_matching(httpx_mock: HTTPXMock, backend: HTTPXBackend) -> None:
httpx_mock.add_response(match_extensions={"test": "value"}, is_optional=True)
- with httpx.Client() as client:
- with pytest.raises(httpx.TimeoutException) as exception_info:
+ with backend.httpx.Client() as client:
+ with pytest.raises(backend.httpx.TimeoutException) as exception_info:
client.get("https://test_url", extensions={"test": "value2"})
assert (
str(exception_info.value)
@@ -2428,22 +2621,26 @@ def test_extensions_not_matching(httpx_mock: HTTPXMock) -> None:
)
-def test_optional_response_not_matched(httpx_mock: HTTPXMock) -> None:
+def test_optional_response_not_matched(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
# This response is optional and the fact that it was never requested should not trigger anything
httpx_mock.add_response(url="https://test_url", is_optional=True)
httpx_mock.add_response(url="https://test_url2")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url2")
assert response.content == b""
-def test_optional_response_matched(httpx_mock: HTTPXMock) -> None:
+def test_optional_response_matched(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
# This response is optional and the fact that it was never requested should not trigger anything
httpx_mock.add_response(url="https://test_url", is_optional=True)
httpx_mock.add_response(url="https://test_url2")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response1 = client.get("https://test_url")
response2 = client.get("https://test_url2")
assert response1.content == b""
@@ -2451,29 +2648,35 @@ def test_optional_response_matched(httpx_mock: HTTPXMock) -> None:
@pytest.mark.httpx_mock(assert_all_responses_were_requested=False)
-def test_mandatory_response_matched(httpx_mock: HTTPXMock) -> None:
+def test_mandatory_response_matched(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
# This response is optional and the fact that it was never requested should not trigger anything
httpx_mock.add_response(url="https://test_url")
# This response MUST be requested (overrides global settings via marker)
httpx_mock.add_response(url="https://test_url2", is_optional=False)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url2")
assert response.content == b""
-def test_multi_response_matched_once(httpx_mock: HTTPXMock) -> None:
+def test_multi_response_matched_once(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url", is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response = client.get("https://test_url")
assert response.content == b""
-def test_multi_response_matched_twice(httpx_mock: HTTPXMock) -> None:
+def test_multi_response_matched_twice(
+ httpx_mock: HTTPXMock, backend: HTTPXBackend
+) -> None:
httpx_mock.add_response(url="https://test_url", is_reusable=True)
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
response1 = client.get("https://test_url")
response2 = client.get("https://test_url")
assert response1.content == b""
diff --git a/tests/test_plugin.py b/tests/test_plugin.py
index 13ed9ea..977536a 100644
--- a/tests/test_plugin.py
+++ b/tests/test_plugin.py
@@ -1,22 +1,26 @@
+import pytest
from pytest import Testdir
+from pytest_httpx import get_backends
+
+pytestmark = pytest.mark.usefixtures("plugin_tests_conftest")
-def test_fixture_is_available(testdir: Testdir) -> None:
- # create a temporary pytest test file
- testdir.makepyfile("""
- import httpx
+def backends_count() -> int:
+ return len(get_backends())
- def test_http(httpx_mock):
+
+def test_fixture_is_available(testdir: Testdir) -> None:
+ testdir.makepyfile("""
+ def test_http(httpx_mock, backend):
mock = httpx_mock.add_response(url="https://foo.tld")
- r = httpx.get("https://foo.tld")
+ r = backend.httpx.get("https://foo.tld")
assert httpx_mock.get_request() is not None
""")
- # run all tests with pytest
result = testdir.runpytest()
- result.assert_outcomes(passed=1)
+ result.assert_outcomes(passed=backends_count())
def test_httpx_mock_unused_response(testdir: Testdir) -> None:
@@ -24,11 +28,11 @@ def test_httpx_mock_unused_response(testdir: Testdir) -> None:
Unused responses should fail test case.
"""
testdir.makepyfile("""
- def test_httpx_mock_unused_response(httpx_mock):
+ def test_httpx_mock_unused_response(httpx_mock, backend):
httpx_mock.add_response()
""")
result = testdir.runpytest()
- result.assert_outcomes(errors=1, passed=1)
+ result.assert_outcomes(errors=backends_count(), passed=backends_count())
result.stdout.fnmatch_lines(
[
"*AssertionError: The following responses are mocked but not requested:",
@@ -49,11 +53,11 @@ def test_httpx_mock_unused_response_without_assertion(testdir: Testdir) -> None:
import pytest
@pytest.mark.httpx_mock(assert_all_responses_were_requested=False)
- def test_httpx_mock_unused_response_without_assertion(httpx_mock):
+ def test_httpx_mock_unused_response_without_assertion(httpx_mock, backend):
httpx_mock.add_response()
""")
result = testdir.runpytest()
- result.assert_outcomes(passed=1)
+ result.assert_outcomes(passed=backends_count())
def test_httpx_mock_unused_callback(testdir: Testdir) -> None:
@@ -61,7 +65,7 @@ def test_httpx_mock_unused_callback(testdir: Testdir) -> None:
Unused callbacks should fail test case.
"""
testdir.makepyfile("""
- def test_httpx_mock_unused_callback(httpx_mock):
+ def test_httpx_mock_unused_callback(httpx_mock, backend):
def unused(*args, **kwargs):
pass
@@ -69,7 +73,7 @@ def unused(*args, **kwargs):
""")
result = testdir.runpytest()
- result.assert_outcomes(errors=1, passed=1)
+ result.assert_outcomes(errors=backends_count(), passed=backends_count())
result.stdout.fnmatch_lines(
[
"*AssertionError: The following responses are mocked but not requested:",
@@ -90,7 +94,7 @@ def test_httpx_mock_unused_callback_without_assertion(testdir: Testdir) -> None:
import pytest
@pytest.mark.httpx_mock(assert_all_responses_were_requested=False)
- def test_httpx_mock_unused_callback_without_assertion(httpx_mock):
+ def test_httpx_mock_unused_callback_without_assertion(httpx_mock, backend):
def unused(*args, **kwargs):
pass
@@ -98,7 +102,7 @@ def unused(*args, **kwargs):
""")
result = testdir.runpytest()
- result.assert_outcomes(passed=1)
+ result.assert_outcomes(passed=backends_count())
def test_httpx_mock_unexpected_request(testdir: Testdir) -> None:
@@ -107,17 +111,16 @@ def test_httpx_mock_unexpected_request(testdir: Testdir) -> None:
assert_all_requests_were_expected option is set to True (default).
"""
testdir.makepyfile("""
- import httpx
import pytest
- def test_httpx_mock_unexpected_request(httpx_mock):
- with httpx.Client() as client:
+ def test_httpx_mock_unexpected_request(httpx_mock, backend):
+ with backend.httpx.Client() as client:
# Non mocked request
- with pytest.raises(httpx.TimeoutException):
+ with pytest.raises(backend.httpx.TimeoutException):
client.get("https://foo.tld")
""")
result = testdir.runpytest()
- result.assert_outcomes(errors=1, passed=1)
+ result.assert_outcomes(errors=backends_count(), passed=backends_count())
result.stdout.fnmatch_lines(
[
"*AssertionError: The following requests were not expected:",
@@ -135,18 +138,17 @@ def test_httpx_mock_unexpected_request_without_assertion(testdir: Testdir) -> No
assert_all_requests_were_expected option is set to False.
"""
testdir.makepyfile("""
- import httpx
import pytest
@pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
- def test_httpx_mock_unexpected_request(httpx_mock):
- with httpx.Client() as client:
+ def test_httpx_mock_unexpected_request(httpx_mock, backend):
+ with backend.httpx.Client() as client:
# Non mocked request
- with pytest.raises(httpx.TimeoutException):
+ with pytest.raises(backend.httpx.TimeoutException):
client.get("https://foo.tld")
""")
result = testdir.runpytest()
- result.assert_outcomes(passed=1)
+ result.assert_outcomes(passed=backends_count())
def test_httpx_mock_already_matched_response(testdir: Testdir) -> None:
@@ -155,19 +157,18 @@ def test_httpx_mock_already_matched_response(testdir: Testdir) -> None:
can_send_already_matched_responses option is set to False (default).
"""
testdir.makepyfile("""
- import httpx
import pytest
- def test_httpx_mock_already_matched_response(httpx_mock):
+ def test_httpx_mock_already_matched_response(httpx_mock, backend):
httpx_mock.add_response()
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.get("https://foo.tld")
# Non mocked (already matched) request
- with pytest.raises(httpx.TimeoutException):
+ with pytest.raises(backend.httpx.TimeoutException):
client.get("https://foo.tld")
""")
result = testdir.runpytest()
- result.assert_outcomes(errors=1, passed=1)
+ result.assert_outcomes(errors=backends_count(), passed=backends_count())
result.stdout.fnmatch_lines(
[
"*AssertionError: The following requests were not expected:",
@@ -185,41 +186,39 @@ def test_httpx_mock_reusing_matched_response(testdir: Testdir) -> None:
can_send_already_matched_responses option is set to True.
"""
testdir.makepyfile("""
- import httpx
import pytest
@pytest.mark.httpx_mock(can_send_already_matched_responses=True)
- def test_httpx_mock_reusing_matched_response(httpx_mock):
+ def test_httpx_mock_reusing_matched_response(httpx_mock, backend):
httpx_mock.add_response()
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.get("https://foo.tld")
# Reusing response
client.get("https://foo.tld")
""")
result = testdir.runpytest()
- result.assert_outcomes(passed=1)
+ result.assert_outcomes(passed=backends_count())
def test_httpx_mock_unmatched_request_without_responses(
testdir: Testdir,
) -> None:
testdir.makepyfile("""
- import httpx
import pytest
- def test_httpx_mock_unmatched_request_without_responses(httpx_mock):
- with httpx.Client() as client:
+ def test_httpx_mock_unmatched_request_without_responses(httpx_mock, backend):
+ with backend.httpx.Client() as client:
# This request will not be matched
client.get("https://foo22.tld")
# This code will not be reached
client.get("https://foo3.tld")
""")
result = testdir.runpytest()
- result.assert_outcomes(errors=1, failed=1)
+ result.assert_outcomes(errors=backends_count(), failed=backends_count())
# Assert the error that occurred
- result.stdout.fnmatch_lines(
+ result.stdout.re_match_lines(
[
- "*httpx.TimeoutException: No response can be found for GET request on https://foo22.tld",
+ r".*httpx2?\.TimeoutException: No response can be found for GET request on https://foo22\.tld",
],
consecutive=True,
)
@@ -239,40 +238,39 @@ def test_httpx_mock_unmatched_request_with_only_unmatched_responses(
testdir: Testdir,
) -> None:
testdir.makepyfile("""
- import httpx
import pytest
- def test_httpx_mock_unmatched_request_with_only_unmatched_responses(httpx_mock):
+ def test_httpx_mock_unmatched_request_with_only_unmatched_responses(httpx_mock, backend):
# This response will not be sent (because of a typo in the URL)
httpx_mock.add_response(url="https://foo2.tld")
# This response will not be sent (because test execution failed earlier)
httpx_mock.add_response(url="https://foo3.tld")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
# This request will not be matched
client.get("https://foo22.tld")
# This code will not be reached
client.get("https://foo3.tld")
""")
result = testdir.runpytest()
- result.assert_outcomes(errors=1, failed=1)
+ result.assert_outcomes(errors=backends_count(), failed=backends_count())
# Assert the error that occurred
- result.stdout.fnmatch_lines(
+ result.stdout.re_match_lines(
[
- "*httpx.TimeoutException: No response can be found for GET request on https://foo22.tld amongst:",
- "*- Match any request on https://foo2.tld",
- "*- Match any request on https://foo3.tld",
+ r".*httpx2?\.TimeoutException: No response can be found for GET request on https://foo22\.tld amongst:",
+ r".*- Match any request on https://foo2\.tld",
+ r".*- Match any request on https://foo3\.tld",
],
consecutive=True,
)
# Assert the teardown assertion failure
result.stdout.fnmatch_lines(
[
- "*AssertionError: The following responses are mocked but not requested:",
- "* - Match any request on https://foo2.tld",
- "* - Match any request on https://foo3.tld",
- "* ",
- "* If this is on purpose, refer to https://github.com/Colin-b/pytest_httpx/blob/master/README.md#allow-to-register-more-responses-than-what-will-be-requested",
+ r"*AssertionError: The following responses are mocked but not requested:",
+ r"* - Match any request on https://foo2.tld",
+ r"* - Match any request on https://foo3.tld",
+ r"* ",
+ r"* If this is on purpose, refer to https://github.com/Colin-b/pytest_httpx/blob/master/README.md#allow-to-register-more-responses-than-what-will-be-requested",
],
consecutive=True,
)
@@ -282,30 +280,29 @@ def test_httpx_mock_unmatched_request_with_only_unmatched_reusable_responses(
testdir: Testdir,
) -> None:
testdir.makepyfile("""
- import httpx
import pytest
@pytest.mark.httpx_mock(can_send_already_matched_responses=True)
- def test_httpx_mock_unmatched_request_with_only_unmatched_responses(httpx_mock):
+ def test_httpx_mock_unmatched_request_with_only_unmatched_responses(httpx_mock, backend):
# This response will not be sent (because of a typo in the URL)
httpx_mock.add_response(url="https://foo2.tld", method="GET")
# This response will not be sent (because test execution failed earlier)
httpx_mock.add_response(url="https://foo3.tld")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
# This request will not be matched
client.get("https://foo22.tld")
# This code will not be reached
client.get("https://foo3.tld")
""")
result = testdir.runpytest()
- result.assert_outcomes(errors=1, failed=1)
+ result.assert_outcomes(errors=backends_count(), failed=backends_count())
# Assert the error that occurred
- result.stdout.fnmatch_lines(
+ result.stdout.re_match_lines(
[
- "*httpx.TimeoutException: No response can be found for GET request on https://foo22.tld amongst:",
- "*- Match GET request on https://foo2.tld",
- "*- Match every request on https://foo3.tld",
+ r".*httpx2?\.TimeoutException: No response can be found for GET request on https://foo22\.tld amongst:",
+ r".*- Match GET request on https://foo2\.tld",
+ r".*- Match every request on https://foo3\.tld",
],
consecutive=True,
)
@@ -326,16 +323,15 @@ def test_httpx_mock_unmatched_request_with_only_matched_responses(
testdir: Testdir,
) -> None:
testdir.makepyfile("""
- import httpx
import pytest
- def test_httpx_mock_unmatched_request_with_only_matched_responses(httpx_mock):
+ def test_httpx_mock_unmatched_request_with_only_matched_responses(httpx_mock, backend):
# Sent response
httpx_mock.add_response(url="https://foo.tld")
# Sent response
httpx_mock.add_response(url="https://foo.tld")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.get("https://foo.tld")
client.get("https://foo.tld")
# This request will not be matched
@@ -344,15 +340,15 @@ def test_httpx_mock_unmatched_request_with_only_matched_responses(httpx_mock):
client.get("https://foo3.tld")
""")
result = testdir.runpytest()
- result.assert_outcomes(errors=1, failed=1)
+ result.assert_outcomes(errors=backends_count(), failed=backends_count())
# Assert the error that occurred
- result.stdout.fnmatch_lines(
+ result.stdout.re_match_lines(
[
- "*httpx.TimeoutException: No response can be found for GET request on https://foo22.tld amongst:",
- "*- Already matched any request on https://foo.tld",
- "*- Already matched any request on https://foo.tld",
- "*",
- "*If you wanted to reuse an already matched response instead of registering it again, refer to https://github.com/Colin-b/pytest_httpx/blob/master/README.md#allow-to-register-a-response-for-more-than-one-request",
+ r".*httpx2?\.TimeoutException: No response can be found for GET request on https://foo22\.tld amongst:",
+ r".*- Already matched any request on https://foo\.tld",
+ r".*- Already matched any request on https://foo\.tld",
+ ".*",
+ r".*If you wanted to reuse an already matched response instead of registering it again, refer to https://github\.com/Colin-b/pytest_httpx/blob/master/README.md#allow-to-register-a-response-for-more-than-one-request",
],
consecutive=True,
)
@@ -372,17 +368,16 @@ def test_httpx_mock_unmatched_request_with_only_matched_reusable_responses(
testdir: Testdir,
) -> None:
testdir.makepyfile("""
- import httpx
import pytest
@pytest.mark.httpx_mock(can_send_already_matched_responses=True)
- def test_httpx_mock_unmatched_request_with_only_matched_responses(httpx_mock):
+ def test_httpx_mock_unmatched_request_with_only_matched_responses(httpx_mock, backend):
# Sent response
httpx_mock.add_response(url="https://foo.tld")
# Sent response
httpx_mock.add_response(url="https://foo3.tld")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.get("https://foo.tld")
client.get("https://foo.tld")
client.get("https://foo3.tld")
@@ -392,13 +387,13 @@ def test_httpx_mock_unmatched_request_with_only_matched_responses(httpx_mock):
client.get("https://foo3.tld")
""")
result = testdir.runpytest()
- result.assert_outcomes(errors=1, failed=1)
+ result.assert_outcomes(errors=backends_count(), failed=backends_count())
# Assert the error that occurred
- result.stdout.fnmatch_lines(
+ result.stdout.re_match_lines(
[
- "*httpx.TimeoutException: No response can be found for GET request on https://foo22.tld amongst:",
- "*- Match every request on https://foo.tld",
- "*- Match every request on https://foo3.tld",
+ r".*httpx2?\.TimeoutException: No response can be found for GET request on https://foo22\.tld amongst:",
+ r".*- Match every request on https://foo\.tld",
+ r".*- Match every request on https://foo3\.tld",
],
consecutive=True,
)
@@ -418,10 +413,9 @@ def test_httpx_mock_unmatched_request_with_matched_and_unmatched_responses(
testdir: Testdir,
) -> None:
testdir.makepyfile("""
- import httpx
import pytest
- def test_httpx_mock_unmatched_request_with_matched_and_unmatched_responses(httpx_mock):
+ def test_httpx_mock_unmatched_request_with_matched_and_unmatched_responses(httpx_mock, backend):
# Sent response
httpx_mock.add_response(url="https://foo.tld")
# This response will not be sent (because of a typo in the URL)
@@ -431,7 +425,7 @@ def test_httpx_mock_unmatched_request_with_matched_and_unmatched_responses(httpx
# This response will not be sent (because test execution failed earlier)
httpx_mock.add_response(url="https://foo3.tld")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.get("https://foo.tld")
client.get("https://foo.tld")
# This request will not be matched
@@ -440,17 +434,17 @@ def test_httpx_mock_unmatched_request_with_matched_and_unmatched_responses(httpx
client.get("https://foo3.tld")
""")
result = testdir.runpytest()
- result.assert_outcomes(errors=1, failed=1)
+ result.assert_outcomes(errors=backends_count(), failed=backends_count())
# Assert the error that occurred
- result.stdout.fnmatch_lines(
+ result.stdout.re_match_lines(
[
- "*httpx.TimeoutException: No response can be found for GET request on https://foo22.tld amongst:",
- "*- Match any request on https://foo2.tld",
- "*- Match any request on https://foo3.tld",
- "*- Already matched any request on https://foo.tld",
- "*- Already matched any request on https://foo.tld",
- "*",
- "*If you wanted to reuse an already matched response instead of registering it again, refer to https://github.com/Colin-b/pytest_httpx/blob/master/README.md#allow-to-register-a-response-for-more-than-one-request",
+ r".*httpx2?\.TimeoutException: No response can be found for GET request on https://foo22\.tld amongst:",
+ r".*- Match any request on https://foo2\.tld",
+ r".*- Match any request on https://foo3\.tld",
+ r".*- Already matched any request on https://foo\.tld",
+ r".*- Already matched any request on https://foo\.tld",
+ ".*",
+ r".*If you wanted to reuse an already matched response instead of registering it again, refer to https://github\.com/Colin-b/pytest_httpx/blob/master/README.md#allow-to-register-a-response-for-more-than-one-request",
],
consecutive=True,
)
@@ -471,11 +465,10 @@ def test_httpx_mock_unmatched_request_with_matched_and_unmatched_reusable_respon
testdir: Testdir,
) -> None:
testdir.makepyfile("""
- import httpx
import pytest
@pytest.mark.httpx_mock(can_send_already_matched_responses=True)
- def test_httpx_mock_unmatched_request_with_matched_and_unmatched_responses(httpx_mock):
+ def test_httpx_mock_unmatched_request_with_matched_and_unmatched_responses(httpx_mock, backend):
# Sent response
httpx_mock.add_response(url="https://foo.tld")
# This response will not be sent (because of a typo in the URL)
@@ -485,7 +478,7 @@ def test_httpx_mock_unmatched_request_with_matched_and_unmatched_responses(httpx
# This response will not be sent (because test execution failed earlier)
httpx_mock.add_response(url="https://foo4.tld")
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
client.get("https://foo.tld")
client.get("https://foo2.tld")
client.get("https://foo.tld")
@@ -495,15 +488,15 @@ def test_httpx_mock_unmatched_request_with_matched_and_unmatched_responses(httpx
client.get("https://foo2.tld")
""")
result = testdir.runpytest()
- result.assert_outcomes(errors=1, failed=1)
+ result.assert_outcomes(errors=backends_count(), failed=backends_count())
# Assert the error that occurred
- result.stdout.fnmatch_lines(
+ result.stdout.re_match_lines(
[
- "*httpx.TimeoutException: No response can be found for GET request on https://foo3.tld amongst:",
- "*- Match every request on https://foo33.tld",
- "*- Match every request on https://foo4.tld",
- "*- Match every request on https://foo.tld",
- "*- Match every request on https://foo2.tld",
+ r".*httpx2?.TimeoutException: No response can be found for GET request on https://foo3\.tld amongst:",
+ r".*- Match every request on https://foo33\.tld",
+ r".*- Match every request on https://foo4\.tld",
+ r".*- Match every request on https://foo\.tld",
+ r".*- Match every request on https://foo2\.tld",
],
consecutive=True,
)
@@ -525,19 +518,18 @@ def test_httpx_mock_should_mock_sync(testdir: Testdir) -> None:
Non mocked requests should go through while other requests should be mocked.
"""
testdir.makepyfile("""
- import httpx
import pytest
@pytest.mark.httpx_mock(should_mock=lambda request: request.url.host != "localhost")
- def test_httpx_mock_should_mock_sync(httpx_mock):
+ def test_httpx_mock_should_mock_sync(httpx_mock, backend):
httpx_mock.add_response()
- with httpx.Client() as client:
+ with backend.httpx.Client() as client:
# Mocked request
client.get("https://foo.tld")
# Non mocked request
- with pytest.raises(httpx.ConnectError):
+ with pytest.raises(backend.httpx.ConnectError):
client.get("https://localhost:5005")
# Assert that a single request was mocked
@@ -545,7 +537,7 @@ def test_httpx_mock_should_mock_sync(httpx_mock):
""")
result = testdir.runpytest()
- result.assert_outcomes(passed=1)
+ result.assert_outcomes(passed=backends_count())
def test_httpx_mock_should_mock_async(testdir: Testdir) -> None:
@@ -553,20 +545,19 @@ def test_httpx_mock_should_mock_async(testdir: Testdir) -> None:
Non mocked requests should go through while other requests should be mocked.
"""
testdir.makepyfile("""
- import httpx
import pytest
@pytest.mark.asyncio
@pytest.mark.httpx_mock(should_mock=lambda request: request.url.host != "localhost")
- async def test_httpx_mock_should_mock_async(httpx_mock):
+ async def test_httpx_mock_should_mock_async(httpx_mock, backend):
httpx_mock.add_response()
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
# Mocked request
await client.get("https://foo.tld")
# Non mocked request
- with pytest.raises(httpx.ConnectError):
+ with pytest.raises(backend.httpx.ConnectError):
await client.get("https://localhost:5005")
# Assert that a single request was mocked
@@ -574,7 +565,7 @@ async def test_httpx_mock_should_mock_async(httpx_mock):
""")
result = testdir.runpytest()
- result.assert_outcomes(passed=1)
+ result.assert_outcomes(passed=backends_count())
def test_httpx_mock_options_on_multi_levels_are_aggregated(testdir: Testdir) -> None:
@@ -587,37 +578,40 @@ def test_httpx_mock_options_on_multi_levels_are_aggregated(testdir: Testdir) ->
"""
testdir.makeconftest("""
import pytest
+ from pytest_httpx import get_backends
+ @pytest.fixture(params=get_backends(), ids=lambda b: b.name)
+ def backend(request):
+ return request.param
def pytest_collection_modifyitems(session, config, items):
for item in items:
item.add_marker(pytest.mark.httpx_mock(assert_all_responses_were_requested=False))
""")
testdir.makepyfile("""
- import httpx
import pytest
pytestmark = pytest.mark.httpx_mock(assert_all_requests_were_expected=False, should_mock=lambda request: request.url.host != "https://foo.tld")
@pytest.mark.asyncio
@pytest.mark.httpx_mock(should_mock=lambda request: request.url.host != "localhost")
- async def test_httpx_mock_options_on_multi_levels_are_aggregated(httpx_mock):
+ async def test_httpx_mock_options_on_multi_levels_are_aggregated(httpx_mock, backend):
httpx_mock.add_response(url="https://foo.tld", headers={"x-pytest-httpx": "this was mocked"})
# This response will never be used, testing that assert_all_responses_were_requested is handled
httpx_mock.add_response(url="https://never_called.url")
- async with httpx.AsyncClient() as client:
+ async with backend.httpx.AsyncClient() as client:
# Assert that previously set should_mock was overridden
response = await client.get("https://foo.tld")
assert response.headers["x-pytest-httpx"] == "this was mocked"
# Assert that latest should_mock is handled
- with pytest.raises(httpx.ConnectError):
+ with pytest.raises(backend.httpx.ConnectError):
await client.get("https://localhost:5005")
# Assert that assert_all_requests_were_expected is the one at module level
- with pytest.raises(httpx.TimeoutException):
+ with pytest.raises(backend.httpx.TimeoutException):
await client.get("https://unexpected.url")
# Assert that 2 requests out of 3 were mocked
@@ -625,7 +619,7 @@ async def test_httpx_mock_options_on_multi_levels_are_aggregated(httpx_mock):
""")
result = testdir.runpytest()
- result.assert_outcomes(passed=1)
+ result.assert_outcomes(passed=backends_count())
def test_invalid_marker(testdir: Testdir) -> None:
@@ -636,12 +630,12 @@ def test_invalid_marker(testdir: Testdir) -> None:
import pytest
@pytest.mark.httpx_mock(foo=123)
- def test_invalid_marker(httpx_mock):
+ def test_invalid_marker(httpx_mock, backend):
pass
""")
result = testdir.runpytest()
- result.assert_outcomes(errors=1)
+ result.assert_outcomes(errors=backends_count())
result.stdout.re_match_lines([r".*got an unexpected keyword argument 'foo'"])
@@ -650,11 +644,10 @@ def test_mandatory_response_not_matched(testdir: Testdir) -> None:
is_optional MUST take precedence over assert_all_responses_were_requested.
"""
testdir.makepyfile("""
- import httpx
import pytest
@pytest.mark.httpx_mock(assert_all_responses_were_requested=False)
- def test_mandatory_response_not_matched(httpx_mock):
+ def test_mandatory_response_not_matched(httpx_mock, backend):
# This response is optional and the fact that it was never requested should not trigger anything
httpx_mock.add_response(url="https://test_url")
# This response MUST be requested
@@ -662,7 +655,7 @@ def test_mandatory_response_not_matched(httpx_mock):
""")
result = testdir.runpytest()
- result.assert_outcomes(errors=1, passed=1)
+ result.assert_outcomes(errors=backends_count(), passed=backends_count())
# Assert the teardown assertion failure
result.stdout.fnmatch_lines(
[
@@ -677,14 +670,12 @@ def test_mandatory_response_not_matched(httpx_mock):
def test_reusable_response_not_matched(testdir: Testdir) -> None:
testdir.makepyfile("""
- import httpx
-
- def test_reusable_response_not_matched(httpx_mock):
+ def test_reusable_response_not_matched(httpx_mock, backend):
httpx_mock.add_response(url="https://test_url2", is_reusable=True)
""")
result = testdir.runpytest()
- result.assert_outcomes(errors=1, passed=1)
+ result.assert_outcomes(errors=backends_count(), passed=backends_count())
# Assert the teardown assertion failure
result.stdout.fnmatch_lines(
[
diff --git a/tox.toml b/tox.toml
new file mode 100644
index 0000000..48640cd
--- /dev/null
+++ b/tox.toml
@@ -0,0 +1,18 @@
+env_list = ["clean", "httpx", "httpx2", "both"]
+
+[env_run_base]
+# Editable mode so that coverage measures the repo source.
+package = "editable"
+extras = ["testing", "{env_name}"]
+commands = [
+ ["pytest", "--cov-append", { replace = "posargs", extend = true }],
+]
+
+[env.clean]
+skip_install = true
+deps = ["coverage[toml]"]
+commands = [["coverage", "erase"]]
+
+[env.both]
+# The "both" environment needs both extras, so override the {env_name}-derived one.
+extras = ["testing", "httpx", "httpx2"]