responses
responses copied to clipboard
Cannot match empty query parameters
Describe the bug
The matcher query_param_matcher cannot match query parameters that have an empty string value.
Additional context
This is because RequestsMock._parse_request_params calls parse_qsl with the default argument keep_blank_values=False:
https://github.com/getsentry/responses/blob/cdd104d2852ef2c8c9eeabbe3ba56c4ca4e29e74/responses/init.py#L1054
This should be configurable, similar to allow_blank in urlencoded_params_matcher (see #533).
Version of responses
0.25.8
Steps to Reproduce
import responses
import requests
from responses import matchers
@responses.activate
def test_empty_query_param():
responses.get("http://example.com/foo", match=[matchers.query_param_matcher({"bar": ""})], json={})
response = requests.get("http://example.com/foo?bar=")
assert response.status_code == 200
Expected Result
The test passes.
Actual Result
The test fails:
E requests.exceptions.ConnectionError: Connection refused by Responses - the call doesn't match any registered mock.
E
E Request:
E - GET http://example.com/foo?bar=
E
E Available matches:
E - GET http://example.com/foo Parameters do not match. {} doesn't match {'bar': ''}
This can be worked around by using a custom RequestsMock:
class AllowEmptyQueryParamRequestsMock(RequestsMock):
def _parse_request_params(self, url: str) -> dict[str, str | int | float | list[str | int | float | None]]:
# Copy of RequestsMock._parse_request_params:
params: dict[str, str | int | float | list[Any]] = {}
# Allow empty query parameters
for key, val in groupby(parse_qsl(urlsplit(url).query, keep_blank_values=True), lambda kv: kv[0]):
values = list(map(lambda x: x[1], val))
if len(values) == 1:
values = values[0] # type: ignore[assignment]
params[key] = values
return params