0

requests 在 Python 中,使用库来发出 HTTP 请求是很常见的。

import requests

r = requests.get('http://google.com')
print(f"Code: {r.status_code}\nText head: {r.text[:100]}")

>>> Code: 200
>>> Text head: <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="es"><head><meta content

responses 然后,使用library模拟 HTTP 请求也很常见。

import requests
import responses

@responses.activate
def my_request():
    responses.add(responses.GET, 'http://google.com', body="Hi! Mocked :)")
    r = requests.get('http://google.com')
    return r

r = my_request()
print(f"Code: {r.status_code}\nText head: {r.text[:100]}")

>>> Code: 200
>>> Text head: Hi! Mocked :)

但是,我有一个用例,我需要模拟一个端点,并实际使用另一个端点。

例如,实际访问'http://google.com'端点以运行函数,然后模拟来自另一个端点的其他数据并测试我的函数。

但是,在这种情况下,我发现我真正想要访问的端点失败只是因为在responses当前的模拟端点中不可用。

import requests
import responses

@responses.activate
def my_request():
    responses.add(responses.GET, 'http://google.com', body="Hi! Mocked :)")
    # To be mocked
    r1 = requests.get('http://google.com')
    # To actually access
    r2 = requests.get('http://bing.com')
    return r1, r2

r1, r2 = my_request()
print(f"Code r1: {r1.status_code}\nCode r2: {r2.status_code}")

作为输出产生:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 3, in wrapper
  File "<stdin>", line 7, in my_request
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/requests/api.py", line 76, in get
    return request('get', url, params=params, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/requests/api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/requests/sessions.py", line 542, in request
    resp = self.send(prep, **send_kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/requests/sessions.py", line 655, in send
    r = adapter.send(request, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/responses/__init__.py", line 765, in unbound_on_send
    return self._on_request(adapter, request, *a, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/responses/__init__.py", line 745, in _on_request
    raise response
requests.exceptions.ConnectionError: Connection refused by Responses - the call doesn't match any registered mock.

Request:
- GET http://bing.com/

Available matches:
- GET http://google.com/ URL does not match

我怎样才能responses允许到达一些实际的非模拟端点?

4

1 回答 1

0

responses 库有一种机制允许使用该add_passthru函数。它的行为类似于add函数,但它只需要endpoint并且不需要进一步的数据。

同样重要的是要注意,如果端点解析为不同的 URL,它将不起作用。例如,将其添加到示例中:

import requests
import responses

@responses.activate
def my_request():
    responses.add(responses.GET, 'http://google.com', body="Hi! Mocked :)")
    responses.add_passthru('http://bing.com')
    # To be mocked
    r1 = requests.get('http://google.com')
    # To actually access
    r2 = requests.get('http://bing.com')
    return r1, r2

r1, r2 = my_request()
print(f"Code r1: {r1.status_code}\nCode r2: {r2.status_code}")

将产生错误,因为r2请求将尝试连接到http://www.bing.com,并且端点是在没有定义的情况下定义的wwwhttp://bing.com

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 3, in wrapper
  File "<stdin>", line 8, in my_request
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/requests/api.py", line 76, in get
    return request('get', url, params=params, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/requests/api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/requests/sessions.py", line 542, in request
    resp = self.send(prep, **send_kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/requests/sessions.py", line 677, in send
    history = [resp for resp in gen]
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/requests/sessions.py", line 677, in <listcomp>
    history = [resp for resp in gen]
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/requests/sessions.py", line 237, in resolve_redirects
    resp = self.send(
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/requests/sessions.py", line 655, in send
    r = adapter.send(request, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/responses/__init__.py", line 765, in unbound_on_send
    return self._on_request(adapter, request, *a, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/responses/__init__.py", line 745, in _on_request
    raise response
requests.exceptions.ConnectionError: Connection refused by Responses - the call doesn't match any registered mock.

Request:
- GET http://www.bing.com/

修改passthru定义的端点将解决这个问题:

    # responses.add_passthru('http://bing.com')
    responses.add_passthru('http://www.bing.com')
于 2021-05-06T08:40:57.297 回答