Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python "responses" mock - unable to call one URL multiple times

I'm using python responses module to mock API response in my tests. The problem is that after the url is registered responses.add() it can be called only once with requests.get(), subsequent calls for the same URL raise an exception.

import requests
import responses

URL = 'http://localhost/abcd'

# Test method
@responses.activate
def get_url(url):
  return requests.get(url)

# Set up URL mock
responses.add(responses.GET, URL, body="A B C D")

Now the first call works:

>>> print(get_url(URL))   # <Response [200]>

However the same call again fails:

>>> print(get_url(URL))

Traceback (most recent call last):
  File "test-responses.py", line 19, in <module>
    print(get_url(URL))
  File "<string>", line 3, in wrapper
  File "test-responses.py", line 10, in get_url
    return requests.get(url)
  File ".../site-packages/requests/api.py", line 75, in get
    return request('get', url, params=params, **kwargs)
  File ".../site-packages/requests/api.py", line 60, in request
    return session.request(method=method, url=url, **kwargs)
  File ".../site-packages/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File ".../site-packages/requests/sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File ".../site-packages/responses.py", line 674, in unbound_on_send
    return self._on_request(adapter, request, *a, **kwargs)
  File ".../site-packages/responses.py", line 654, in _on_request
    raise response
requests.exceptions.ConnectionError: Connection refused by Responses - the call doesn't match any registered mock.

Request: 
- GET http://localhost/abcd

Available matches:

>>>

Is there any way to make the mock URLs permanent and call them as many times as the tests need?

like image 391
MLu Avatar asked Mar 24 '26 13:03

MLu


1 Answers

The problem with your original code is that get_url wrapped with decorator and it creates a new responses context every time when get_url is called, but response.add register url mock is registered only once - for the first response context.

@response.activate decorator intended to be used for test cases. Here is correct way of using decorator that allows to make requests to same url.

@responses.activate
def test_function():
    responses.add(responses.GET, URL, body="A B C D")
    print(get_url(URL))
    print(get_url(URL))

test_function()

Using responses.start() / responses.stop() allows to make many requests for the same URL.


import requests
import responses

URL = 'http://localhost/abcd'

def get_url(url):
    return requests.get(url)

# Test method
responses.start()
# Set up URL mock
responses.add(responses.GET, URL, body="A B C D")
print(get_url(URL))
print(get_url(URL))
responses.stop()

For unit tests I'm using this mixing code .

BTW Latest responses version (0.12.0) has function assert_calls_count that allows to check the number of requests to url without exception.

assert responses.assert_call_count(URL, 1) is True
like image 78
vvladymyrov Avatar answered Mar 27 '26 11:03

vvladymyrov