pythonapipython-requestsmockingpython-responses

python responses library prepends part of the URL to the request params


I am trying to mock an external API using the responses library. I want to check I've passed my params correctly in my request, so I am using this minimum working example from the responses docs:

import responses
import requests

@responses.activate
def test_request_params():
    responses.add(
        method=responses.GET,
        url="http://example.com?hello=world",
        body="test",
        match_querystring=False,
    )

    resp = requests.get('http://example.com', params={"hello": "world"})
    assert responses.calls[0].request.params == {"hello": "world"}

The problem is, this breaks as soon as I replace http://example.com with a URL that resembles an API endpoint:

@responses.activate
def test_request_params():
    responses.add(
        method=responses.GET,
        url="http://example.com/api/endpoint?hello=world",
        body="test",
        match_querystring=False,
    )

    resp = requests.get('http://example.com/api/endpoint', params={"hello": "world"})
    assert responses.calls[0].request.params == {"hello": "world"}

Now responses has added part of the URL to the first query param:

>       assert responses.calls[0].request.params == {"hello": "world"}
E       AssertionError: assert {'/api/endpoint?hello': 'world'} == {'hello': 'world'}

Am I missing something?


Solution

  • You can pass a regex as the url argument, which ignores parameters:

    @responses.activate
    def test_request_params():
    
        url = r"http://example.com/api/endpoint"
        params = {"hello": "world", "a": "b"}
    
        # regex that matches the url and ignores anything that comes after
        rx = re.compile(rf"{url}*")
        responses.add(method=responses.GET, url=rx)
    
        response = requests.get(url, params=params)
        assert responses.calls[-1].request.params == params
    
        url_path, *queries = responses.calls[-1].request.url.split("?")
        assert url_path == url