Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pytest-httpx for 
openSUSE:Factory checked in at 2026-04-14 17:49:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pytest-httpx (Old)
 and      /work/SRC/openSUSE:Factory/.python-pytest-httpx.new.21863 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pytest-httpx"

Tue Apr 14 17:49:14 2026 rev:13 rq:1346510 version:0.36.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pytest-httpx/python-pytest-httpx.changes  
2024-12-16 19:17:10.138543991 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-pytest-httpx.new.21863/python-pytest-httpx.changes
       2026-04-14 17:49:55.875536869 +0200
@@ -1,0 +2,19 @@
+Mon Apr 13 06:12:01 UTC 2026 - Steve Kowalik <[email protected]>
+
+- Update to 0.36.2:
+  ## Changed
+  * pytest required version is now 9.
+  ## Added
+  * Explicit support for python 3.14.
+  * match_params parameter is now available on responses and callbacks
+    registration, as well as request(s) retrieval. Allowing to provide query
+    parameters as a dict instead of being part of the matched URL.
+    + This parameter allows to perform partial query params matching.
+  ## Fixed
+  * URL with more than one value for the same parameter were not matched
+    properly (matching was performed on the first value).
+  * httpx_mock.add_exception is now properly documented.
+  ## Removed
+  * python 3.9 is not supported anymore.
+
+-------------------------------------------------------------------

Old:
----
  pytest_httpx-0.35.0-gh.tar.gz

New:
----
  _scmsync.obsinfo
  build.specials.obscpio
  pytest_httpx-0.36.2-gh.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pytest-httpx.spec ++++++
--- /var/tmp/diff_new_pack.jKbdFe/_old  2026-04-14 17:49:56.983582669 +0200
+++ /var/tmp/diff_new_pack.jKbdFe/_new  2026-04-14 17:49:56.987582835 +0200
@@ -18,24 +18,24 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-pytest-httpx
-Version:        0.35.0
+Version:        0.36.2
 Release:        0
 Summary:        Send responses to httpx
 License:        MIT
 URL:            https://colin-b.github.io/pytest_httpx/
-Source:         
https://github.com/Colin-b/pytest_httpx/archive/refs/tags/v%{version}.tar.gz#/pytest_httpx-%{version}-gh.tar.gz
-BuildRequires:  %{python_module base >= 3.9}
+Source:         
https://github.com/Colin-b/pytest_httpx/archive/refs/tags/%{version}.tar.gz#/pytest_httpx-%{version}-gh.tar.gz
+BuildRequires:  %{python_module base >= 3.10}
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  %{python_module wheel}
 BuildRequires:  python-rpm-macros
 # SECTION test requirements
 BuildRequires:  %{python_module httpx >= 0.28.0 with %python-httpx < 0.29}
-BuildRequires:  %{python_module pytest >= 8.0}
+BuildRequires:  %{python_module pytest >= 9.0}
 BuildRequires:  %{python_module pytest-asyncio >= 0.24.0}
 # /SECTION
 BuildRequires:  fdupes
-Requires:       python-pytest >= 8.0
+Requires:       python-pytest >= 9.0
 Requires:       (python-httpx >= 0.28.0 with python-httpx < 0.29)
 BuildArch:      noarch
 %python_subpackages

++++++ _scmsync.obsinfo ++++++
mtime: 1776060734
commit: 23fd6bbfcc31b2e1c5c97ca8f2ec249fe643afb1e497683acf8e94b0d690fd98
url: https://src.opensuse.org/python-pytest/python-pytest-httpx.git
revision: 23fd6bbfcc31b2e1c5c97ca8f2ec249fe643afb1e497683acf8e94b0d690fd98
projectscmsync: https://src.opensuse.org/python-pytest/_ObsPrj.git

++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore      1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore      2026-04-14 02:15:49.000000000 +0200
@@ -0,0 +1 @@
+.osc

++++++ pytest_httpx-0.35.0-gh.tar.gz -> pytest_httpx-0.36.2-gh.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest_httpx-0.35.0/.github/workflows/release.yml 
new/pytest_httpx-0.36.2/.github/workflows/release.yml
--- old/pytest_httpx-0.35.0/.github/workflows/release.yml       2024-11-28 
20:16:16.000000000 +0100
+++ new/pytest_httpx-0.36.2/.github/workflows/release.yml       2026-04-09 
15:55:54.000000000 +0200
@@ -1,26 +1,46 @@
-name: Release
+name: Publish Python 🐍 distribution 📦 to PyPI
 
 on:
   push:
-    branches:
-      - master
+    tags:
+      - "*"
 
 jobs:
   build:
-
+    name: Build distribution 📦
     runs-on: ubuntu-latest
-
     steps:
-    - uses: actions/checkout@v4
-    - name: Set up Python
-      uses: actions/setup-python@v5
+    - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 # v6.0.2
+    - name: Set up Python 🐍
+      uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # 
v6.2.0
       with:
-        python-version: '3.13'
-    - name: Create packages
+        python-version: '3.14'
+    - name: Build a binary wheel and a source tarball
       run: |
-        python -m pip install build
+        python -m pip install pip==26.0.1
+        python -m pip install build==1.4.2
         python -m build .
-    - name: Publish packages
-      run: |
-        python -m pip install twine
-        python -m twine upload dist/* --skip-existing --username __token__ 
--password ${{ secrets.pypi_password }}
+    - name: Store the distribution packages
+      uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 
v7.0.0
+      with:
+        name: python-package-distributions
+        path: dist/
+  pypi-publish:
+    name: >-
+      Publish Python 🐍 distribution 📦 to PyPI
+    needs:
+      - build
+    runs-on: ubuntu-latest
+    environment:
+      name: pypi
+      url: https://pypi.org/project/pytest-httpx/${{ github.ref_name }}
+    permissions:
+      id-token: write
+    steps:
+      - name: Download all the dists
+        uses: 
actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
+        with:
+          name: python-package-distributions
+          path: dist/
+      - name: Publish distribution 📦 to PyPI
+        uses: 
pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest_httpx-0.35.0/.github/workflows/test.yml 
new/pytest_httpx-0.36.2/.github/workflows/test.yml
--- old/pytest_httpx-0.35.0/.github/workflows/test.yml  2024-11-28 
20:16:16.000000000 +0100
+++ new/pytest_httpx-0.36.2/.github/workflows/test.yml  2026-04-09 
15:55:54.000000000 +0200
@@ -8,22 +8,26 @@
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
+        python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
 
     steps:
-    - uses: actions/checkout@v4
+    - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 # v6.0.2
     - name: Set up Python ${{ matrix.python-version }}
-      uses: actions/setup-python@v5
+      uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # 
v6.2.0
       with:
         python-version: ${{ matrix.python-version }}
     - name: Install dependencies
       run: |
-        python -m pip install --upgrade pip
+        python -m pip install pip==26.0.1
         python -m pip install -e .[testing]
+        python -m pip install pre-commit==4.5.1
+    - name: Ensure pre-commit was applied
+      run: |
+        pre-commit run --all-files
     - name: Test
       run: |
         pytest --cov=pytest_httpx --cov-fail-under=100 
--cov-report=term-missing --runpytest=subprocess
     - name: Test packages creation
       run: |
-        python -m pip install build
+        python -m pip install build==1.4.2
         python -m build .
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest_httpx-0.35.0/.pre-commit-config.yaml 
new/pytest_httpx-0.36.2/.pre-commit-config.yaml
--- old/pytest_httpx-0.35.0/.pre-commit-config.yaml     2024-11-28 
20:16:16.000000000 +0100
+++ new/pytest_httpx-0.36.2/.pre-commit-config.yaml     2026-04-09 
15:55:54.000000000 +0200
@@ -1,5 +1,5 @@
 repos:
   - repo: https://github.com/psf/black
-    rev: 24.10.0
+    rev: 26.3.1
     hooks:
       - id: black
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest_httpx-0.35.0/CHANGELOG.md 
new/pytest_httpx-0.36.2/CHANGELOG.md
--- old/pytest_httpx-0.35.0/CHANGELOG.md        2024-11-28 20:16:16.000000000 
+0100
+++ new/pytest_httpx-0.36.2/CHANGELOG.md        2026-04-09 15:55:54.000000000 
+0200
@@ -6,6 +6,27 @@
 
 ## [Unreleased]
 
+## [0.36.2] - 2026-04-09
+### Fixed
+- Document how to ignore query parameters while matching on URL.
+
+## [0.36.0] - 2025-12-02
+### Changed
+- `pytest` required version is now `9`.
+
+### Added
+- Explicit support for python `3.14`.
+- `match_params` parameter is now available on responses and callbacks 
registration, as well as request(s) retrieval. Allowing to provide query 
parameters as a dict instead of being part of the matched URL.
+  - This parameter allows to perform partial query params matching ([refer to 
documentation](README.md#matching-on-query-parameters) for more information).
+
+### Fixed
+- URL with more than one value for the same parameter were not matched 
properly (matching was performed on the first value).
+- `httpx_mock.add_exception` is now properly documented (accepts 
`BaseException` instead of `Exception`).
+
+### Removed
+- `pytest` `8` is not supported anymore.
+- python `3.9` is not supported anymore.
+
 ## [0.35.0] - 2024-11-28
 ### Changed
 - Requires [`httpx`](https://www.python-httpx.org)==0.28.\*
@@ -408,7 +429,9 @@
 ### Added
 - First release, should be considered as unstable for now as design might 
change.
 
-[Unreleased]: https://github.com/Colin-b/pytest_httpx/compare/v0.35.0...HEAD
+[Unreleased]: https://github.com/Colin-b/pytest_httpx/compare/0.36.2...HEAD
+[0.36.2]: https://github.com/Colin-b/pytest_httpx/compare/v0.36.0...0.36.2
+[0.36.0]: https://github.com/Colin-b/pytest_httpx/compare/v0.35.0...v0.36.0
 [0.35.0]: https://github.com/Colin-b/pytest_httpx/compare/v0.34.0...v0.35.0
 [0.34.0]: https://github.com/Colin-b/pytest_httpx/compare/v0.33.0...v0.34.0
 [0.33.0]: https://github.com/Colin-b/pytest_httpx/compare/v0.32.0...v0.33.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest_httpx-0.35.0/LICENSE 
new/pytest_httpx-0.36.2/LICENSE
--- old/pytest_httpx-0.35.0/LICENSE     2024-11-28 20:16:16.000000000 +0100
+++ new/pytest_httpx-0.36.2/LICENSE     2026-04-09 15:55:54.000000000 +0200
@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2024 Colin Bounouar
+Copyright (c) 2026 Colin Bounouar
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest_httpx-0.35.0/README.md 
new/pytest_httpx-0.36.2/README.md
--- old/pytest_httpx-0.35.0/README.md   2024-11-28 20:16:16.000000000 +0100
+++ new/pytest_httpx-0.36.2/README.md   2026-04-09 15:55:54.000000000 +0200
@@ -5,7 +5,7 @@
 <a href="https://github.com/Colin-b/pytest_httpx/actions";><img alt="Build 
status" 
src="https://github.com/Colin-b/pytest_httpx/workflows/Release/badge.svg";></a>
 <a href="https://github.com/Colin-b/pytest_httpx/actions";><img alt="Coverage" 
src="https://img.shields.io/badge/coverage-100%25-brightgreen";></a>
 <a href="https://github.com/psf/black";><img alt="Code style: black" 
src="https://img.shields.io/badge/code%20style-black-000000.svg";></a>
-<a href="https://github.com/Colin-b/pytest_httpx/actions";><img alt="Number of 
tests" src="https://img.shields.io/badge/tests-272 passed-blue"></a>
+<a href="https://github.com/Colin-b/pytest_httpx/actions";><img alt="Number of 
tests" src="https://img.shields.io/badge/tests-298 passed-blue"></a>
 <a href="https://pypi.org/project/pytest-httpx/";><img alt="Number of 
downloads" src="https://img.shields.io/pypi/dm/pytest_httpx";></a>
 </p>
 
@@ -107,6 +107,50 @@
         response = client.get("https://test_url?a=1&b=2";)
 ```
 
+##### Ignoring query parameters
+
+Use a python [re.Pattern](https://docs.python.org/3/library/re.html) instance 
to ignore query parameters while matching on the URL.
+
+```python
+import httpx
+import re
+from pytest_httpx import HTTPXMock
+
+
+def test_url_as_pattern_ignoring_query_parameters(httpx_mock: HTTPXMock):
+    httpx_mock.add_response(url=re.compile("https://test_url/something.*";))
+
+    with httpx.Client() as client:
+        response = client.get("https://test_url/something?a=1&b=2";)
+        assert response.content == b""
+```
+
+#### Matching on query parameters
+
+Use `match_params` to partially match query parameters without having to 
provide a regular expression as `url`.
+
+If this parameter is provided, `url` parameter must not contain any query 
parameter.
+
+All query parameters have to be provided (as `str`). You can however use 
`unittest.mock.ANY` to do partial matching.
+
+```python
+import httpx
+from pytest_httpx import HTTPXMock
+from unittest.mock import ANY
+
+def test_partial_params_matching(httpx_mock: HTTPXMock):
+    httpx_mock.add_response(url="https://test_url";, match_params={"a": "1", 
"b": ANY})
+
+    with httpx.Client() as client:
+        response = client.get("https://test_url?a=1&b=2";)
+
+def test_partial_multi_params_matching(httpx_mock: HTTPXMock):
+    httpx_mock.add_response(url="https://test_url";, match_params={"a": ["1", 
"3"], "b": ["2", ANY]})
+
+    with httpx.Client() as client:
+        response = client.get("https://test_url?a=1&b=2&a=3&b=4";)
+```
+
 #### Matching on HTTP method
 
 Use `method` parameter to specify the HTTP method (POST, PUT, DELETE, PATCH, 
HEAD) to reply to.
@@ -473,7 +517,7 @@
 
 Cookies are sent in the `set-cookie` HTTP header.
 
-You can then send cookies in the response by setting the `set-cookie` header 
with [the value following key=value 
format]((https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie)).
+You can then send cookies in the response by setting the `set-cookie` header 
with [the value following key=value 
format](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie).
 
 ```python
 import httpx
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest_httpx-0.35.0/pyproject.toml 
new/pytest_httpx-0.36.2/pyproject.toml
--- old/pytest_httpx-0.35.0/pyproject.toml      2024-11-28 20:16:16.000000000 
+0100
+++ new/pytest_httpx-0.36.2/pyproject.toml      2026-04-09 15:55:54.000000000 
+0200
@@ -6,13 +6,13 @@
 name = "pytest-httpx"
 description = "Send responses to httpx."
 readme = "README.md"
-requires-python = ">=3.9"
+requires-python = ">=3.10"
 license = {file = "LICENSE"}
 authors = [
-    { name = "Colin Bounouar", email = "[email protected]" },
+    { name = "Colin Bounouar", email = "[email protected]" },
 ]
 maintainers = [
-    { name = "Colin Bounouar", email = "[email protected]" },
+    { name = "Colin Bounouar", email = "[email protected]" },
 ]
 keywords = [
     "httpx",
@@ -27,18 +27,18 @@
     "Natural Language :: English",
     "Programming Language :: Python",
     "Programming Language :: Python :: 3",
-    "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3.12",
     "Programming Language :: Python :: 3.13",
+    "Programming Language :: Python :: 3.14",
     "Topic :: Internet :: WWW/HTTP",
     "Topic :: Software Development :: Build Tools",
     "Typing :: Typed",
 ]
 dependencies = [
     "httpx==0.28.*",
-    "pytest==8.*",
+    "pytest==9.*",
 ]
 dynamic = ["version"]
 
@@ -51,9 +51,9 @@
 [project.optional-dependencies]
 testing = [
     # Used to check coverage
-    "pytest-cov==6.*",
+    "pytest-cov==7.*",
     # Used to run async tests
-    "pytest-asyncio==0.24.*",
+    "pytest-asyncio==1.*",
 ]
 
 [project.entry-points.pytest11]
@@ -62,6 +62,9 @@
 [tool.setuptools.dynamic]
 version = {attr = "pytest_httpx.version.__version__"}
 
-[tool.pytest.ini_options]
+[tool.pytest]
 # Silence deprecation warnings about option 
"asyncio_default_fixture_loop_scope"
 asyncio_default_fixture_loop_scope = "function"
+
+[tool.coverage.run]
+patch = ["subprocess"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest_httpx-0.35.0/pytest_httpx/_httpx_internals.py 
new/pytest_httpx-0.36.2/pytest_httpx/_httpx_internals.py
--- old/pytest_httpx-0.35.0/pytest_httpx/_httpx_internals.py    2024-11-28 
20:16:16.000000000 +0100
+++ new/pytest_httpx-0.36.2/pytest_httpx/_httpx_internals.py    2026-04-09 
15:55:54.000000000 +0200
@@ -52,7 +52,7 @@
 
 
 def _proxy_url(
-    real_transport: Union[httpx.HTTPTransport, httpx.AsyncHTTPTransport]
+    real_transport: Union[httpx.HTTPTransport, httpx.AsyncHTTPTransport],
 ) -> Optional[httpx.URL]:
     if isinstance(
         real_pool := real_transport._pool, (httpcore.HTTPProxy, 
httpcore.AsyncHTTPProxy)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest_httpx-0.35.0/pytest_httpx/_httpx_mock.py 
new/pytest_httpx-0.36.2/pytest_httpx/_httpx_mock.py
--- old/pytest_httpx-0.35.0/pytest_httpx/_httpx_mock.py 2024-11-28 
20:16:16.000000000 +0100
+++ new/pytest_httpx-0.36.2/pytest_httpx/_httpx_mock.py 2026-04-09 
15:55:54.000000000 +0200
@@ -58,7 +58,7 @@
         :param html: HTTP body of the response (as HTML string content).
         :param stream: HTTP body of the response (as httpx.SyncByteStream or 
httpx.AsyncByteStream) as stream content.
         :param json: HTTP body of the response (if JSON should be used as 
content type) if data is not provided.
-        :param url: Full URL identifying the request(s) to match.
+        :param url: Full URL identifying the request(s) to match. Use in 
addition to match_params if you do not want to provide query parameters as part 
of the URL.
         Can be a str, a re.Pattern instance or a httpx.URL instance.
         :param method: HTTP method identifying the request(s) to match.
         :param proxy_url: Full proxy URL identifying the request(s) to match.
@@ -68,6 +68,8 @@
         :param match_json: JSON decoded HTTP body identifying the request(s) 
to match. Must be JSON encodable.
         :param match_data: Multipart data (excluding files) identifying the 
request(s) to match. Must be a dictionary.
         :param match_files: Multipart files identifying the request(s) to 
match. Refer to httpx documentation for more information on supported values: 
https://www.python-httpx.org/advanced/clients/#multipart-file-encoding
+        :param match_extensions: Extensions identifying the request(s) to 
match. Must be a dictionary.
+        :param match_params: Query string parameters identifying the 
request(s) to match (if not provided as part of URL already). Must be a 
dictionary with str keys (parameter name) and str values (or a list of str 
values if parameter is provided more than once).
         :param is_optional: True will mark this response as optional, False 
will expect a request matching it. Must be a boolean. Default to the opposite 
of assert_all_responses_were_requested option value (itself defaulting to True, 
meaning this parameter default to False).
         :param is_reusable: True will allow re-using this 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).
         """
@@ -101,7 +103,7 @@
 
         :param callback: The callable that will be called upon reception of 
the matched request.
         It must expect one parameter, the received httpx.Request and should 
return a httpx.Response.
-        :param url: Full URL identifying the request(s) to match.
+        :param url: Full URL identifying the request(s) to match. Use in 
addition to match_params if you do not want to provide query parameters as part 
of the URL.
         Can be a str, a re.Pattern instance or a httpx.URL instance.
         :param method: HTTP method identifying the request(s) to match.
         :param proxy_url: Full proxy URL identifying the request(s) to match.
@@ -112,17 +114,18 @@
         :param match_data: Multipart data (excluding files) identifying the 
request(s) to match. Must be a dictionary.
         :param match_files: Multipart files identifying the request(s) to 
match. Refer to httpx documentation for more information on supported values: 
https://www.python-httpx.org/advanced/clients/#multipart-file-encoding
         :param match_extensions: Extensions identifying the request(s) to 
match. Must be a dictionary.
+        :param match_params: Query string parameters identifying the 
request(s) to match (if not provided as part of URL already). Must be a 
dictionary with str keys (parameter name) and str values (or a list of str 
values if parameter is provided more than once).
         :param is_optional: True will mark this callback as optional, False 
will expect a request matching it. Must be a boolean. Default to the opposite 
of assert_all_responses_were_requested option value (itself defaulting to True, 
meaning this parameter default to False).
         :param is_reusable: True will allow re-using this callback 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).
         """
         self._callbacks.append((_RequestMatcher(self._options, **matchers), 
callback))
 
-    def add_exception(self, exception: Exception, **matchers: Any) -> None:
+    def add_exception(self, exception: BaseException, **matchers: Any) -> None:
         """
         Raise an exception if a request match.
 
         :param exception: The exception that will be raised upon reception of 
the matched request.
-        :param url: Full URL identifying the request(s) to match.
+        :param url: Full URL identifying the request(s) to match. Use in 
addition to match_params if you do not want to provide query parameters as part 
of the URL.
         Can be a str, a re.Pattern instance or a httpx.URL instance.
         :param method: HTTP method identifying the request(s) to match.
         :param proxy_url: Full proxy URL identifying the request(s) to match.
@@ -133,6 +136,7 @@
         :param match_data: Multipart data (excluding files) identifying the 
request(s) to match. Must be a dictionary.
         :param match_files: Multipart files identifying the request(s) to 
match. Refer to httpx documentation for more information on supported values: 
https://www.python-httpx.org/advanced/clients/#multipart-file-encoding
         :param match_extensions: Extensions identifying the request(s) to 
match. Must be a dictionary.
+        :param match_params: Query string parameters identifying the 
request(s) to match (if not provided as part of URL already). Must be a 
dictionary with str keys (parameter name) and str values (or a list of str 
values if parameter is provided more than once).
         :param is_optional: True will mark this exception response as 
optional, False will expect a request matching it. Must be a boolean. Default 
to the opposite of assert_all_responses_were_requested option value (itself 
defaulting to True, meaning this parameter default to False).
         :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).
         """
@@ -261,7 +265,7 @@
         """
         Return all requests sent that match (empty list if no requests were 
matched).
 
-        :param url: Full URL identifying the requests to retrieve.
+        :param url: Full URL identifying the requests to retrieve. Use in 
addition to match_params if you do not want to provide query parameters as part 
of the URL.
         Can be a str, a re.Pattern instance or a httpx.URL instance.
         :param method: HTTP method identifying the requests to retrieve. Must 
be an upper-cased string value.
         :param proxy_url: Full proxy URL identifying the requests to retrieve.
@@ -272,6 +276,7 @@
         :param match_data: Multipart data (excluding files) identifying the 
requests to retrieve. Must be a dictionary.
         :param match_files: Multipart files identifying the requests to 
retrieve. Refer to httpx documentation for more information on supported 
values: https://www.python-httpx.org/advanced/clients/#multipart-file-encoding
         :param match_extensions: Extensions identifying the requests to 
retrieve. Must be a dictionary.
+        :param match_params: Query string parameters identifying the requests 
to retrieve (if not provided as part of URL already). Must be a dictionary with 
str keys (parameter name) and str values (or a list of str values if parameter 
is provided more than once).
         """
         matcher = _RequestMatcher(self._options, **matchers)
         return [
@@ -284,7 +289,7 @@
         """
         Return the single request that match (or None).
 
-        :param url: Full URL identifying the request to retrieve.
+        :param url: Full URL identifying the request to retrieve. Use in 
addition to match_params if you do not want to provide query parameters as part 
of the URL.
         Can be a str, a re.Pattern instance or a httpx.URL instance.
         :param method: HTTP method identifying the request to retrieve. Must 
be an upper-cased string value.
         :param proxy_url: Full proxy URL identifying the request to retrieve.
@@ -295,6 +300,7 @@
         :param match_data: Multipart data (excluding files) identifying the 
request to retrieve. Must be a dictionary.
         :param match_files: Multipart files identifying the request to 
retrieve. Refer to httpx documentation for more information on supported 
values: https://www.python-httpx.org/advanced/clients/#multipart-file-encoding
         :param match_extensions: Extensions identifying the request to 
retrieve. Must be a dictionary.
+        :param match_params: Query string parameters identifying the request 
to retrieve (if not provided as part of URL already). Must be a dictionary with 
str keys (parameter name) and str values (or a list of str values if parameter 
is provided more than once).
         :raises AssertionError: in case more than one request match.
         """
         requests = self.get_requests(**matchers)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest_httpx-0.35.0/pytest_httpx/_request_matcher.py 
new/pytest_httpx-0.36.2/pytest_httpx/_request_matcher.py
--- old/pytest_httpx-0.35.0/pytest_httpx/_request_matcher.py    2024-11-28 
20:16:16.000000000 +0100
+++ new/pytest_httpx-0.36.2/pytest_httpx/_request_matcher.py    2026-04-09 
15:55:54.000000000 +0200
@@ -4,20 +4,24 @@
 from re import Pattern
 
 import httpx
+from httpx import QueryParams
 
 from pytest_httpx._httpx_internals import _proxy_url
 from pytest_httpx._options import _HTTPXMockOptions
 
 
 def _url_match(
-    url_to_match: Union[Pattern[str], httpx.URL], received: httpx.URL
+    url_to_match: Union[Pattern[str], httpx.URL],
+    received: httpx.URL,
+    params: Optional[dict[str, Union[str | list[str]]]],
 ) -> bool:
     if isinstance(url_to_match, re.Pattern):
         return url_to_match.match(str(received)) is not None
 
     # Compare query parameters apart as order of parameters should not matter
-    received_params = dict(received.params)
-    params = dict(url_to_match.params)
+    received_params = to_params_dict(received.params)
+    if params is None:
+        params = to_params_dict(url_to_match.params)
 
     # Remove the query parameters from the original URL to compare everything 
besides query parameters
     received_url = received.copy_with(query=None)
@@ -26,6 +30,15 @@
     return (received_params == params) and (url == received_url)
 
 
+def to_params_dict(params: QueryParams) -> dict[str, Union[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:
+        values = params.get_list(key)
+        d[key] = values if len(values) > 1 else values[0]
+    return d
+
+
 class _RequestMatcher:
     def __init__(
         self,
@@ -39,6 +52,7 @@
         match_data: Optional[dict[str, Any]] = None,
         match_files: Optional[Any] = None,
         match_extensions: Optional[dict[str, Any]] = None,
+        match_params: Optional[dict[str, Union[str | list[str]]]] = None,
         is_optional: Optional[bool] = None,
         is_reusable: Optional[bool] = None,
     ):
@@ -51,14 +65,23 @@
         self.json = match_json
         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.extensions = match_extensions
-        self.is_optional = not options.assert_all_responses_were_requested if 
is_optional is None else is_optional
-        self.is_reusable = options.can_send_already_matched_responses if 
is_reusable is None else is_reusable
+        self.is_optional = (
+            not options.assert_all_responses_were_requested
+            if is_optional is None
+            else is_optional
+        )
+        self.is_reusable = (
+            options.can_send_already_matched_responses
+            if is_reusable is None
+            else is_reusable
+        )
         if self._is_matching_body_more_than_one_way():
             raise ValueError(
                 "Only one way of matching against the body can be provided. "
@@ -66,6 +89,16 @@
                 "If you want to match against the multipart representation, 
use match_files (and match_data). "
                 "Otherwise, use match_content."
             )
+        if self.params and not self.url:
+            raise ValueError("URL must be provided when match_params is used.")
+        if self.params and isinstance(self.url, re.Pattern):
+            raise ValueError(
+                "match_params cannot be used in addition to regex URL. Request 
this feature via 
https://github.com/Colin-b/pytest_httpx/issues/new?title=Regex%20URL%20should%20allow%20match_params&body=Hi,%20I%20need%20a%20regex%20to%20match%20the%20non%20query%20part%20of%20the%20URL%20only";
+            )
+        if self._is_matching_params_more_than_one_way():
+            raise ValueError(
+                "Provided URL must not contain any query parameter when 
match_params is used."
+            )
         if self.data and not self.files:
             raise ValueError(
                 "match_data is meant to be used for multipart matching (in 
conjunction with match_files)."
@@ -88,6 +121,18 @@
         ]
         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
+        )
+        matching_ways = [
+            self.params is not None,
+            url_has_params,
+        ]
+        return sum(matching_ways) > 1
+
     def match(
         self,
         real_transport: Union[httpx.HTTPTransport, httpx.AsyncHTTPTransport],
@@ -106,7 +151,7 @@
         if not self.url:
             return True
 
-        return _url_match(self.url, request.url)
+        return _url_match(self.url, request.url, self.params)
 
     def _method_match(self, request: httpx.Request) -> bool:
         if not self.method:
@@ -168,7 +213,7 @@
             return True
 
         if real_proxy_url := _proxy_url(real_transport):
-            return _url_match(self.proxy_url, real_proxy_url)
+            return _url_match(self.proxy_url, real_proxy_url, params=None)
 
         return False
 
@@ -200,6 +245,8 @@
     def _extra_description(self) -> str:
         extra_description = []
 
+        if self.params:
+            extra_description.append(f"{self.params} query parameters")
         if self.headers:
             extra_description.append(f"{self.headers} headers")
         if self.content is not None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest_httpx-0.35.0/pytest_httpx/version.py 
new/pytest_httpx-0.36.2/pytest_httpx/version.py
--- old/pytest_httpx-0.35.0/pytest_httpx/version.py     2024-11-28 
20:16:16.000000000 +0100
+++ new/pytest_httpx-0.36.2/pytest_httpx/version.py     2026-04-09 
15:55:54.000000000 +0200
@@ -3,4 +3,4 @@
 # Major should be incremented in case there is a breaking change. (eg: 2.5.8 
-> 3.0.0)
 # Minor should be incremented in case there is an enhancement. (eg: 2.5.8 -> 
2.6.0)
 # Patch should be incremented in case there is a bug fix. (eg: 2.5.8 -> 2.5.9)
-__version__ = "0.35.0"
+__version__ = "0.36.2"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest_httpx-0.35.0/tests/test_httpx_async.py 
new/pytest_httpx-0.36.2/tests/test_httpx_async.py
--- old/pytest_httpx-0.35.0/tests/test_httpx_async.py   2024-11-28 
20:16:16.000000000 +0100
+++ new/pytest_httpx-0.36.2/tests/test_httpx_async.py   2026-04-09 
15:55:54.000000000 +0200
@@ -73,6 +73,189 @@
 
 
 @pytest.mark.asyncio
+async def test_url_query_params_partial_matching(httpx_mock: HTTPXMock) -> 
None:
+    httpx_mock.add_response(
+        url=httpx.URL("https://test_url";),
+        match_params={"a": ["1", "3"], "b": ANY, "c": "4", "d": ["5", ANY]},
+        is_reusable=True,
+    )
+
+    async with httpx.AsyncClient() as client:
+        response = await 
client.post("https://test_url?a=1&b=2&a=3&c=4&d=5&d=6";)
+        assert response.content == b""
+
+        # Parameters order should not matter
+        response = await client.get("https://test_url?b=9&a=1&a=3&c=4&d=5&d=7";)
+        assert response.content == b""
+
+
[email protected]
+async def test_url_as_pattern_ignoring_query_parameters(httpx_mock: HTTPXMock):
+    httpx_mock.add_response(url=re.compile("https://test_url/something.*";))
+
+    async with httpx.AsyncClient() as client:
+        response = await client.get("https://test_url/something?a=1&b=2";)
+        assert response.content == b""
+
+
[email protected]
[email protected]_mock(assert_all_requests_were_expected=False)
+async def test_url_query_params_with_single_value_list(httpx_mock: HTTPXMock) 
-> 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:
+            await client.post("https://test_url?a=1";)
+        assert (
+            str(exception_info.value)
+            == """No response can be found for POST request on 
https://test_url?a=1 amongst:
+- Match any request on https://test_url with {'a': ['1']} query parameters"""
+        )
+
+
[email protected]
[email protected]_mock(assert_all_requests_were_expected=False)
+async def test_url_query_params_with_non_str_value(httpx_mock: HTTPXMock) -> 
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:
+            await client.post("https://test_url?a=1";)
+        assert (
+            str(exception_info.value)
+            == """No response can be found for POST request on 
https://test_url?a=1 amongst:
+- Match any request on https://test_url with {'a': 1} query parameters"""
+        )
+
+
[email protected]
[email protected]_mock(assert_all_requests_were_expected=False)
+async def test_url_query_params_with_non_str_list_value(httpx_mock: HTTPXMock) 
-> None:
+    httpx_mock.add_response(
+        url="https://test_url";,
+        match_params={"a": [1, "2"]},
+        is_optional=True,
+    )
+
+    async with httpx.AsyncClient() as client:
+        with pytest.raises(httpx.TimeoutException) as exception_info:
+            await client.post("https://test_url?a=1&a=2";)
+        assert (
+            str(exception_info.value)
+            == """No response can be found for POST request on 
https://test_url?a=1&a=2 amongst:
+- Match any request on https://test_url with {'a': [1, '2']} query 
parameters"""
+        )
+
+
[email protected]
[email protected]_mock(assert_all_requests_were_expected=False)
+async def test_url_query_params_with_non_str_name(httpx_mock: HTTPXMock) -> 
None:
+    httpx_mock.add_response(
+        url="https://test_url";,
+        match_params={1: "1"},
+        is_optional=True,
+    )
+
+    async with httpx.AsyncClient() as client:
+        with pytest.raises(httpx.TimeoutException) as exception_info:
+            await client.post("https://test_url?1=1";)
+        assert (
+            str(exception_info.value)
+            == """No response can be found for POST request on 
https://test_url?1=1 amongst:
+- Match any request on https://test_url with {1: '1'} query parameters"""
+        )
+
+
[email protected]
[email protected]_mock(assert_all_requests_were_expected=False)
+async def test_url_query_params_not_matching(httpx_mock: HTTPXMock) -> 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:
+            await client.post("https://test_url?a=2";)
+        assert (
+            str(exception_info.value)
+            == """No response can be found for POST request on 
https://test_url?a=2 amongst:
+- Match any request on https://test_url with {'a': '1'} query parameters"""
+        )
+
+
[email protected]
+async def test_url_matching_with_more_than_one_value_on_same_param(
+    httpx_mock: HTTPXMock,
+) -> None:
+    httpx_mock.add_response(url="https://test_url?a=1&a=3";, is_optional=True)
+
+    async with httpx.AsyncClient() as client:
+        response = await client.get("https://test_url";, params={"a": [1, 3]})
+        assert response.content == b""
+
+
[email protected]
[email protected]_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,
+) -> 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:
+            await client.get("https://test_url";, params={"a": [1, 3]})
+        assert (
+            str(exception_info.value)
+            == """No response can be found for GET request on 
https://test_url?a=1&a=3 amongst:
+- Match any request on https://test_url?a=2&a=3""";
+        )
+
+
[email protected]
[email protected]_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,
+) -> 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:
+            await client.get("https://test_url";, params={"a": [1, 3, 4]})
+        assert (
+            str(exception_info.value)
+            == """No response can be found for GET request on 
https://test_url?a=1&a=3&a=4 amongst:
+- Match any request on https://test_url?a=1&a=3""";
+        )
+
+
[email protected]
[email protected]_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,
+) -> 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:
+            await client.get("https://test_url";, params={"a": [1, 3]})
+        assert (
+            str(exception_info.value)
+            == """No response can be found for GET request on 
https://test_url?a=1&a=3 amongst:
+- Match any request on https://test_url?a=1&a=3&a=4""";
+        )
+
+
[email protected]
 @pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
 async def test_url_not_matching(httpx_mock: HTTPXMock) -> None:
     httpx_mock.add_response(url="https://test_url";, is_optional=True)
@@ -886,15 +1069,30 @@
 
 
 @pytest.mark.asyncio
-async def test_non_request_exception_raising(httpx_mock: HTTPXMock) -> None:
-    httpx_mock.add_exception(
-        httpx.HTTPError("Unable to read within 5.0"), url="https://test_url";
-    )
[email protected](
+    ("exception_type", "message"),
+    [
+        # httpx exception without request context
+        pytest.param(
+            httpx.HTTPError, "Unable to read within 5.0", 
id="non_request_exception"
+        ),
+        # BaseException derived exception
+        pytest.param(
+            asyncio.CancelledError,
+            "Request was cancelled",
+            id="cancelled_exception",
+        ),
+    ],
+)
+async def test_non_request_exception_raising(
+    httpx_mock: HTTPXMock, exception_type: type, message: str
+) -> None:
+    httpx_mock.add_exception(exception_type(message), url="https://test_url";)
 
     async with httpx.AsyncClient() as client:
-        with pytest.raises(httpx.HTTPError) as exception_info:
+        with pytest.raises(exception_type) as exception_info:
             await client.get("https://test_url";)
-        assert str(exception_info.value) == "Unable to read within 5.0"
+        assert str(exception_info.value) == message
 
 
 @pytest.mark.asyncio
@@ -1087,8 +1285,7 @@
     """
     Single request cannot be returned if there is more than one matching.
     """
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         import pytest
         
@@ -1102,8 +1299,7 @@
                 await client.get("https://test_url";, headers={"X-TEST": "test 
header 2"})
         
             httpx_mock.get_request(url=httpx.URL("https://test_url";))
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(failed=1)
     result.stdout.fnmatch_lines(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest_httpx-0.35.0/tests/test_httpx_sync.py 
new/pytest_httpx-0.36.2/tests/test_httpx_sync.py
--- old/pytest_httpx-0.35.0/tests/test_httpx_sync.py    2024-11-28 
20:16:16.000000000 +0100
+++ new/pytest_httpx-0.36.2/tests/test_httpx_sync.py    2026-04-09 
15:55:54.000000000 +0200
@@ -64,6 +64,207 @@
         assert response.content == b""
 
 
+def test_url_query_params_partial_matching(httpx_mock: HTTPXMock) -> None:
+    httpx_mock.add_response(
+        url="https://test_url";,
+        match_params={"a": ["1", "3"], "b": ANY, "c": "4", "d": ["5", ANY]},
+        is_reusable=True,
+    )
+
+    with httpx.Client() as client:
+        response = client.post("https://test_url?a=1&b=2&a=3&c=4&d=5&d=6";)
+        assert response.content == b""
+
+        # Parameters order should not matter
+        response = client.get("https://test_url?b=9&a=1&a=3&c=4&d=5&d=7";)
+        assert response.content == b""
+
+
+def test_url_as_pattern_ignoring_query_parameters(httpx_mock: HTTPXMock):
+    httpx_mock.add_response(url=re.compile("https://test_url/something.*";))
+
+    with httpx.Client() as client:
+        response = client.get("https://test_url/something?a=1&b=2";)
+        assert response.content == b""
+
+
[email protected]_mock(assert_all_requests_were_expected=False)
+def test_url_query_params_with_single_value_list(httpx_mock: HTTPXMock) -> 
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:
+            client.post("https://test_url?a=1";)
+        assert (
+            str(exception_info.value)
+            == """No response can be found for POST request on 
https://test_url?a=1 amongst:
+- Match any request on https://test_url with {'a': ['1']} query parameters"""
+        )
+
+
[email protected]_mock(assert_all_requests_were_expected=False)
+def test_url_query_params_with_non_str_value(httpx_mock: HTTPXMock) -> 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:
+            client.post("https://test_url?a=1";)
+        assert (
+            str(exception_info.value)
+            == """No response can be found for POST request on 
https://test_url?a=1 amongst:
+- Match any request on https://test_url with {'a': 1} query parameters"""
+        )
+
+
[email protected]_mock(assert_all_requests_were_expected=False)
+def test_url_query_params_with_non_str_list_value(httpx_mock: HTTPXMock) -> 
None:
+    httpx_mock.add_response(
+        url="https://test_url";,
+        match_params={"a": [1, "2"]},
+        is_optional=True,
+    )
+
+    with httpx.Client() as client:
+        with pytest.raises(httpx.TimeoutException) as exception_info:
+            client.post("https://test_url?a=1&a=2";)
+        assert (
+            str(exception_info.value)
+            == """No response can be found for POST request on 
https://test_url?a=1&a=2 amongst:
+- Match any request on https://test_url with {'a': [1, '2']} query 
parameters"""
+        )
+
+
[email protected]_mock(assert_all_requests_were_expected=False)
+def test_url_query_params_with_non_str_name(httpx_mock: HTTPXMock) -> None:
+    httpx_mock.add_response(
+        url="https://test_url";,
+        match_params={1: "1"},
+        is_optional=True,
+    )
+
+    with httpx.Client() as client:
+        with pytest.raises(httpx.TimeoutException) as exception_info:
+            client.post("https://test_url?1=1";)
+        assert (
+            str(exception_info.value)
+            == """No response can be found for POST request on 
https://test_url?1=1 amongst:
+- Match any request on https://test_url with {1: '1'} query parameters"""
+        )
+
+
+def test_match_params_without_url(httpx_mock: HTTPXMock) -> None:
+    with pytest.raises(ValueError) as exception_info:
+        httpx_mock.add_response(match_params={"a": "1"})
+
+    assert (
+        str(exception_info.value) == "URL must be provided when match_params 
is used."
+    )
+
+
+def test_query_params_in_both_url_and_match_params(httpx_mock: HTTPXMock) -> 
None:
+    with pytest.raises(ValueError) as exception_info:
+        httpx_mock.add_response(url="https://test_url?a=1";, match_params={"a": 
"1"})
+
+    assert (
+        str(exception_info.value)
+        == "Provided URL must not contain any query parameter when 
match_params is used."
+    )
+
+
+def test_regex_url_and_match_params(httpx_mock: HTTPXMock) -> None:
+    with pytest.raises(ValueError) as exception_info:
+        httpx_mock.add_response(url=re.compile(".*test.*"), match_params={"a": 
"1"})
+
+    assert (
+        str(exception_info.value)
+        == "match_params cannot be used in addition to regex URL. Request this 
feature via 
https://github.com/Colin-b/pytest_httpx/issues/new?title=Regex%20URL%20should%20allow%20match_params&body=Hi,%20I%20need%20a%20regex%20to%20match%20the%20non%20query%20part%20of%20the%20URL%20only";
+    )
+
+
[email protected]_mock(assert_all_requests_were_expected=False)
+def test_url_query_params_not_matching(httpx_mock: HTTPXMock) -> 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:
+            client.post("https://test_url?a=2";)
+        assert (
+            str(exception_info.value)
+            == """No response can be found for POST request on 
https://test_url?a=2 amongst:
+- Match any request on https://test_url with {'a': '1'} query parameters"""
+        )
+
+
+def test_url_matching_with_more_than_one_value_on_same_param(
+    httpx_mock: HTTPXMock,
+) -> None:
+    httpx_mock.add_response(url="https://test_url?a=1&a=3";, is_optional=True)
+
+    with httpx.Client() as client:
+        response = client.get("https://test_url";, params={"a": [1, 3]})
+        assert response.content == b""
+
+
[email protected]_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,
+) -> 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:
+            client.get("https://test_url";, params={"a": [1, 3]})
+        assert (
+            str(exception_info.value)
+            == """No response can be found for GET request on 
https://test_url?a=1&a=3 amongst:
+- Match any request on https://test_url?a=2&a=3""";
+        )
+
+
[email protected]_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,
+) -> 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:
+            client.get("https://test_url";, params={"a": [1, 3, 4]})
+        assert (
+            str(exception_info.value)
+            == """No response can be found for GET request on 
https://test_url?a=1&a=3&a=4 amongst:
+- Match any request on https://test_url?a=1&a=3""";
+        )
+
+
[email protected]_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,
+) -> 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:
+            client.get("https://test_url";, params={"a": [1, 3]})
+        assert (
+            str(exception_info.value)
+            == """No response can be found for GET request on 
https://test_url?a=1&a=3 amongst:
+- Match any request on https://test_url?a=1&a=3&a=4""";
+        )
+
+
 @pytest.mark.httpx_mock(assert_all_requests_were_expected=False)
 def test_url_not_matching(httpx_mock: HTTPXMock) -> None:
     httpx_mock.add_response(url="https://test_url";, is_optional=True)
@@ -862,8 +1063,7 @@
     """
     Single request cannot be returned if there is more than one matching.
     """
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         
         
@@ -875,8 +1075,7 @@
                 client.get("https://test_url";, headers={"X-TEST": "test header 
2"})
         
             httpx_mock.get_request(url=httpx.URL("https://test_url";))
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(failed=1)
     result.stdout.fnmatch_lines(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest_httpx-0.35.0/tests/test_plugin.py 
new/pytest_httpx-0.36.2/tests/test_plugin.py
--- old/pytest_httpx-0.35.0/tests/test_plugin.py        2024-11-28 
20:16:16.000000000 +0100
+++ new/pytest_httpx-0.36.2/tests/test_plugin.py        2026-04-09 
15:55:54.000000000 +0200
@@ -3,8 +3,7 @@
 
 def test_fixture_is_available(testdir: Testdir) -> None:
     # create a temporary pytest test file
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         
         
@@ -13,8 +12,7 @@
             r = httpx.get("https://foo.tld";)
             assert httpx_mock.get_request() is not None
 
-    """
-    )
+    """)
 
     # run all tests with pytest
     result = testdir.runpytest()
@@ -25,12 +23,10 @@
     """
     Unused responses should fail test case.
     """
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         def test_httpx_mock_unused_response(httpx_mock):
             httpx_mock.add_response()
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(errors=1, passed=1)
     result.stdout.fnmatch_lines(
@@ -49,15 +45,13 @@
     Unused responses should not fail test case if
     assert_all_responses_were_requested option is set to False.
     """
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import pytest
 
         @pytest.mark.httpx_mock(assert_all_responses_were_requested=False)
         def test_httpx_mock_unused_response_without_assertion(httpx_mock):
             httpx_mock.add_response()
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(passed=1)
 
@@ -66,16 +60,14 @@
     """
     Unused callbacks should fail test case.
     """
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         def test_httpx_mock_unused_callback(httpx_mock):
             def unused(*args, **kwargs):
                 pass
         
             httpx_mock.add_callback(unused)
 
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(errors=1, passed=1)
     result.stdout.fnmatch_lines(
@@ -94,8 +86,7 @@
     Unused callbacks should not fail test case if
     assert_all_responses_were_requested option is set to False.
     """
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import pytest
 
         @pytest.mark.httpx_mock(assert_all_responses_were_requested=False)
@@ -105,8 +96,7 @@
         
             httpx_mock.add_callback(unused)
 
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(passed=1)
 
@@ -116,8 +106,7 @@
     Unexpected request should fail test case if
     assert_all_requests_were_expected option is set to True (default).
     """
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         import pytest
 
@@ -126,8 +115,7 @@
                 # Non mocked request
                 with pytest.raises(httpx.TimeoutException):
                     client.get("https://foo.tld";)
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(errors=1, passed=1)
     result.stdout.fnmatch_lines(
@@ -146,8 +134,7 @@
     Unexpected request should not fail test case if
     assert_all_requests_were_expected option is set to False.
     """
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         import pytest
 
@@ -157,8 +144,7 @@
                 # Non mocked request
                 with pytest.raises(httpx.TimeoutException):
                     client.get("https://foo.tld";)
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(passed=1)
 
@@ -168,8 +154,7 @@
     Already matched response should fail test case if
     can_send_already_matched_responses option is set to False (default).
     """
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         import pytest
 
@@ -180,8 +165,7 @@
                 # Non mocked (already matched) request
                 with pytest.raises(httpx.TimeoutException):
                     client.get("https://foo.tld";)
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(errors=1, passed=1)
     result.stdout.fnmatch_lines(
@@ -200,8 +184,7 @@
     Already matched response should not fail test case if
     can_send_already_matched_responses option is set to True.
     """
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         import pytest
 
@@ -212,8 +195,7 @@
                 client.get("https://foo.tld";)
                 # Reusing response
                 client.get("https://foo.tld";)
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(passed=1)
 
@@ -221,8 +203,7 @@
 def test_httpx_mock_unmatched_request_without_responses(
     testdir: Testdir,
 ) -> None:
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         import pytest
 
@@ -232,8 +213,7 @@
                 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)
     # Assert the error that occurred
@@ -258,8 +238,7 @@
 def test_httpx_mock_unmatched_request_with_only_unmatched_responses(
     testdir: Testdir,
 ) -> None:
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         import pytest
 
@@ -274,8 +253,7 @@
                 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)
     # Assert the error that occurred
@@ -303,8 +281,7 @@
 def test_httpx_mock_unmatched_request_with_only_unmatched_reusable_responses(
     testdir: Testdir,
 ) -> None:
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         import pytest
 
@@ -320,8 +297,7 @@
                 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)
     # Assert the error that occurred
@@ -349,8 +325,7 @@
 def test_httpx_mock_unmatched_request_with_only_matched_responses(
     testdir: Testdir,
 ) -> None:
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         import pytest
 
@@ -367,8 +342,7 @@
                 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)
     # Assert the error that occurred
@@ -397,8 +371,7 @@
 def test_httpx_mock_unmatched_request_with_only_matched_reusable_responses(
     testdir: Testdir,
 ) -> None:
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         import pytest
 
@@ -417,8 +390,7 @@
                 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)
     # Assert the error that occurred
@@ -445,8 +417,7 @@
 def test_httpx_mock_unmatched_request_with_matched_and_unmatched_responses(
     testdir: Testdir,
 ) -> None:
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         import pytest
 
@@ -467,8 +438,7 @@
                 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)
     # Assert the error that occurred
@@ -500,8 +470,7 @@
 def 
test_httpx_mock_unmatched_request_with_matched_and_unmatched_reusable_responses(
     testdir: Testdir,
 ) -> None:
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         import pytest
 
@@ -524,8 +493,7 @@
                 client.get("https://foo3.tld";)
                 # This code will not be reached
                 client.get("https://foo2.tld";)
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(errors=1, failed=1)
     # Assert the error that occurred
@@ -556,8 +524,7 @@
     """
     Non mocked requests should go through while other requests should be 
mocked.
     """
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         import pytest
 
@@ -576,8 +543,7 @@
             # Assert that a single request was mocked
             assert len(httpx_mock.get_requests()) == 1
             
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(passed=1)
 
@@ -586,8 +552,7 @@
     """
     Non mocked requests should go through while other requests should be 
mocked.
     """
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         import pytest
 
@@ -607,8 +572,7 @@
             # Assert that a single request was mocked
             assert len(httpx_mock.get_requests()) == 1
             
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(passed=1)
 
@@ -621,18 +585,15 @@
     module: assert_all_requests_were_expected (tested by not mocking one URL)
     test: should_mock (tested by calling 3 URls, 2 mocked, the other one not)
     """
-    testdir.makeconftest(
-        """
+    testdir.makeconftest("""
         import pytest
 
 
         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(
-        """
+    """)
+    testdir.makepyfile("""
         import httpx
         import pytest
 
@@ -662,8 +623,7 @@
             # Assert that 2 requests out of 3 were mocked 
             assert len(httpx_mock.get_requests()) == 2
             
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(passed=1)
 
@@ -672,16 +632,14 @@
     """
     Unknown marker keyword arguments should raise a TypeError.
     """
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import pytest
 
         @pytest.mark.httpx_mock(foo=123)
         def test_invalid_marker(httpx_mock):
             pass
             
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(errors=1)
     result.stdout.re_match_lines([r".*got an unexpected keyword argument 
'foo'"])
@@ -691,8 +649,7 @@
     """
     is_optional MUST take precedence over assert_all_responses_were_requested.
     """
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
         import pytest
 
@@ -703,8 +660,7 @@
             # This response MUST be requested
             httpx_mock.add_response(url="https://test_url2";, is_optional=False)
             
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(errors=1, passed=1)
     # Assert the teardown assertion failure
@@ -720,15 +676,13 @@
 
 
 def test_reusable_response_not_matched(testdir: Testdir) -> None:
-    testdir.makepyfile(
-        """
+    testdir.makepyfile("""
         import httpx
 
         def test_reusable_response_not_matched(httpx_mock):
             httpx_mock.add_response(url="https://test_url2";, is_reusable=True)
             
-    """
-    )
+    """)
     result = testdir.runpytest()
     result.assert_outcomes(errors=1, passed=1)
     # Assert the teardown assertion failure

Reply via email to