首页 > 解决方案 > Python“响应”模拟 - 无法多次调用一个 URL

问题描述

responses在我的测试中使用 python 模块来模拟 API 响应。问题是,在注册 url 后,responses.add()它只能被调用一次requests.get()随后对同一 URL 的调用会引发异常。

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")

现在第一个电话有效:

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

然而,同样的调用再次失败:

>>> 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:

>>>

有没有办法使模拟 URL 永久化并根据测试需要多次调用它们?

标签: pythonunit-testingpython-requestsmocking

解决方案


您的原始代码的问题在于get_url用装饰器包装,并且每次get_url调用时都会创建一个新的响应上下文,但是response.add注册 url 模拟只注册一次 - 对于第一个响应上下文。

@response.activate用于测试用例的装饰器。这是使用允许向相同 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()

使用responses.start() / responses.stop()允许对同一个 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()

对于单元测试,我正在使用这个混合代码。

顺便说一句,最新responses版本(0.12.0)具有函数assert_calls_count允许无一例外地检查对 url 的请求数。

assert responses.assert_call_count(URL, 1) is True

推荐阅读