Skip to content

Commit 6a26429

Browse files
committed
fix(testing): correct async mocker for httpx 0.28 body matching
Address PR review on the httpx 0.28 / pytest-httpx 0.35 bump. - match_content now mirrors httpx 0.28's request-body serialization exactly by adding ensure_ascii=False and allow_nan=False. Without them a non-ASCII match_body serialized to \uXXXX escapes while httpx sends raw UTF-8, so the mock silently failed to match. - Pin an upper bound pytest-httpx >=0.35,<1. It is a runtime dependency (connect.client.testing ships the mocker and a pytest11 plugin) that relies on private pytest_httpx API (_HTTPXMockOptions, _assert_options), so an unbounded minor bump could break downstream test suites. - Add test_create_match_non_ascii_body and test_unrequested_mock_fails to cover the non-ASCII matching and the reset() assertion path, which previously had no coverage.
1 parent c14e8ee commit 6a26429

4 files changed

Lines changed: 22 additions & 4 deletions

File tree

connect/client/testing/fluent.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,14 @@ def mock(
235235

236236
if match_body:
237237
if isinstance(match_body, (dict, list, tuple)):
238-
# httpx>=0.28 serializes JSON request bodies compactly, so match
239-
# the same separators or match_content won't compare equal.
238+
# Mirror httpx>=0.28's request-body serialization exactly, or
239+
# match_content won't compare equal (compact separators, raw
240+
# UTF-8 rather than \uXXXX escapes, and no NaN/Infinity).
240241
kwargs['match_content'] = json.dumps(
241242
match_body,
242243
separators=(',', ':'),
244+
ensure_ascii=False,
245+
allow_nan=False,
243246
).encode('utf-8')
244247
else:
245248
kwargs['match_content'] = match_body

poetry.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ inflect = ">=7"
4242
httpx = ">=0.28"
4343
asgiref = "^3.3.4"
4444
responses = ">=0.14.0,<1"
45-
pytest-httpx = ">=0.35"
45+
pytest-httpx = ">=0.35,<1"
4646

4747
[tool.poetry.group.test.dependencies]
4848
black = "23.*"

tests/async_client/test_testing.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,21 @@ async def test_create():
4949
assert await client.products['product_id'].items.create(payload={}) == {'test': 'data'}
5050

5151

52+
@pytest.mark.asyncio
53+
async def test_create_match_non_ascii_body():
54+
with AsyncConnectClientMocker('http://localhost') as mocker:
55+
mocker.products.create(return_value={'test': 'data'}, match_body={'name': 'Peña'})
56+
client = AsyncConnectClient('api_key', endpoint='http://localhost')
57+
assert await client.products.create(payload={'name': 'Peña'}) == {'test': 'data'}
58+
59+
60+
@pytest.mark.asyncio
61+
async def test_unrequested_mock_fails():
62+
with pytest.raises(AssertionError):
63+
with AsyncConnectClientMocker('http://localhost') as mocker:
64+
mocker.products.create(return_value={'test': 'data'})
65+
66+
5267
@pytest.mark.asyncio
5368
async def test_bulk_create():
5469
with AsyncConnectClientMocker('http://localhost') as mocker:

0 commit comments

Comments
 (0)