Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

responses.add can't mock requests.get(url, params=payload) #148

Closed
ymotongpoo opened this issue May 5, 2017 · 2 comments
Closed

responses.add can't mock requests.get(url, params=payload) #148

ymotongpoo opened this issue May 5, 2017 · 2 comments

Comments

@ymotongpoo
Copy link

my main code uses requests.get(url, params=payload) to access the API with URL parameters, and my test code tried to mock the request with the following code, but it failed with 239: ConnectionError.

Test code:

    @responses.activate
    @pytest.mark.parametrize("test_input, expected", [
        ('https://example.com/', '0')
    ])
    def test_no_bookmark(self, target, test_input, expected):
        request_url = API_ENDPOINT + '?' + urlencode({'url': test_input})
        responses.add(responses.GET, request_url,
                      status=200, content_type='text/plain')
        result = target(test_input)
        assert result == expected

and error message:

self = <tests.test_plugins.test_bot.Test_get_api object at 0x1085bf550>, target = <function get_api at 0x1084aa598>, test_input = 'https://example.com/', expected = 0

    @responses.activate
    @pytest.mark.parametrize("test_input, expected", [
        ('https://example.com/', 0)
    ])
    def test_no_bookmark(self, target, test_input, expected):
        request_url = API_ENDPOINT + \
            '?' + urlencode({'url': test_input})
        responses.add(responses.GET, request_url,
                      status=200, content_type='text/plain')
>       result = target(test_input)

tests/test_plugins/test_bot.py:161:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
plugins/bot.py:152: in get_api
    resp = requests.get(API_ENDPOINT, params=payload)
../../../python/pyspabot/lib/python3.5/site-packages/requests/api.py:70: in get
    return request('get', url, params=params, **kwargs)
../../../python/pyspabot/lib/python3.5/site-packages/requests/api.py:56: in request
    return session.request(method=method, url=url, **kwargs)
../../../python/pyspabot/lib/python3.5/site-packages/requests/sessions.py:488: in request
    resp = self.send(prep, **send_kwargs)
../../../python/pyspabot/lib/python3.5/site-packages/requests/sessions.py:609: in send
    r = adapter.send(request, **kwargs)
../../../python/pyspabot/lib/python3.5/site-packages/responses.py:294: in unbound_on_send
    return self._on_request(adapter, request, *a, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <responses.RequestsMock object at 0x108323668>, adapter = <requests.adapters.HTTPAdapter object at 0x1085bfb38>, request = <PreparedRequest [GET]>
kwargs = {'cert': None, 'proxies': OrderedDict(), 'stream': False, 'timeout': None, ...}, match = None, error_msg = 'Connection refused: GET http://api.foo.com/?url=https%3A%2F%2Fexample.com%2F'
response = ConnectionError('Connection refused: GET http://api.foo.com/?url=https%3A%2F%2Fexample.com%2F',)

    def _on_request(self, adapter, request, **kwargs):
        match = self._find_match(request)
        # TODO(dcramer): find the correct class for this
        if match is None:
            error_msg = 'Connection refused: {0} {1}'.format(request.method,
                                                             request.url)
            response = ConnectionError(error_msg)
            response.request = request

            self._calls.add(request, response)
>           raise response
E           requests.exceptions.ConnectionError: Connection refused: GET http://api.foo.com/?url=https%3A%2F%2Fexample.com%2F

../../../python/pyspabot/lib/python3.5/site-packages/responses.py:239: ConnectionError

And I tried eliminating URL parameters in responses.add() in the test code, i.e.:

    @responses.activate
    @pytest.mark.parametrize("test_input, expected", [
        ('https://example.com/', '0')
    ])
    def test_no_bookmark(self, target, test_input, expected):
        responses.add(responses.GET, API_ENDPOINT,
                      status=200, content_type='text/plain')
        result = target(test_input)
        assert result == expected

This made the test passed. I think responses.add() is not handling params variables in requests.get().

@ruivapps
Copy link

ruivapps commented May 18, 2017

I experience same issue on 0.51 build when I try something like:
http://test.com/abc?state=true

but then I dig into responses.py
the responses is "designed" to not mock the query string

responses.py: the _has_url_match(self, match, request_url) has following:
url_without_qs = request_url.split('?', 1)[0]
return url == url_without_qs

so, change my mock url from
http://test.com/abc?state=true
to
http://test.com/abc

any requests.get('http://test.com/abc?state=true') would work fine

@ifedapoolarewaju
Copy link

If you want to match the exact same url including its query params, it seems you can pass the optional argument match_querystring=True. So you have:

responses.add(responses.GET, request_url, status=200, content_type='text/plain', match_querystring=True)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants