Skip to content

Query param matching with empty values? #181

Open

Description

@plaes

I'm attempting to test scenario where I simulate syncing items against external API that also features pagination.

So basically, I have a call which internally does two calls - first one without cursor parameter and second one with:

    _ = pook.get( 
        "https://api.pipedrive.com:443/api/v2/organizations",
        reply=200,
        response_json=load_json("sample-data-page0.json"),
        params={'cursor': ''},
    )
    _ = pook.get(
        "https://api.pipedrive.com:443/api/v2/organizations",
        reply=200,
        response_json=load_json("sample-data-page1.json"),
        params={"cursor": "eyJmaWVsZCI6ImlkIiwiZmllbGRWYWx1ZSI6ODIzLCJzb3J0RGlyZWN0aW9uIjoiYXNjIiwiaWQiOjgyM30"},
    )

Whatever I attempt, the second call runs against the initial URL even though parameters (or query) shouldn't match.

Simplest reproducable:

import requests
import pook

# Enable mock engine
pook.on()
(
    pook.get("httpbin.org/get")
    .params({"foo": ""})
    .reply(201)
    .json({"error": "simulated"})
)
res = requests.get("http://httpbin.org/get?foo=")

Activity

  1. plaes commented on Apr 27, 2026

    @plaes
    Author

    Not sure whether this is an acceptable patch, considering that there's also a param_exists(name, allow_empty=False)?

    diff --git a/src/pook/matchers/query.py b/src/pook/matchers/query.py
    index 185ac9f..78b8b7b 100644
    --- a/src/pook/matchers/query.py
    +++ b/src/pook/matchers/query.py
    @@ -30,14 +30,14 @@ class QueryMatcher(BaseMatcher):
     
             # Parse and assert type
             if isinstance(query, str):
    -            query = parse_qs(self.expectation)
    +            query = parse_qs(self.expectation, keep_blank_values=True)
     
             # Validate query params
             if not isinstance(query, dict):
                 raise ValueError("query params must be a str or dict")
     
             # Parse request URL query
    -        req_query = parse_qs(req.url.query)
    +        req_query = parse_qs(req.url.query, keep_blank_values=True)
     
             # Match query params
             return self.match_query(query, req_query)
    diff --git a/tests/unit/mock_test.py b/tests/unit/mock_test.py
    index f195893..0aef05c 100644
    --- a/tests/unit/mock_test.py
    +++ b/tests/unit/mock_test.py
    @@ -111,6 +111,11 @@ def test_mock_constructor(param_kwargs, query_string, url_404):
                 "?baz=qux",
                 (False, []),
             ),
    +        (
    +            {"foo": ""},
    +            "?foo",
    +            (True, [])
    +        ),
         ],
     )
     def test_mock_params(url_404, params, req_params, expected, mock):
  2. jharibo commented on Oct 21, 2026

    @jharibo

    Fixed in pookx 2.2.2, a maintained fork of pook that keeps the pook import name. Both parse_qs calls now keep blank values, as suggested above, with docs and tests from #188. Note that an empty value requires the parameter to be present: params({"cursor": ""}) matches ?cursor= but not a request without cursor. More context in #186.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions