【问题标题】:How to allow non mocked endpoints when using responses library使用响应库时如何允许非模拟端点
【发布时间】:2021-05-05 16:44:21
【问题描述】:

在 Python 中,使用 requests library 来发出 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 允许到达一些实际的非模拟端点?

【问题讨论】:

    标签: python python-requests python-responses


    【解决方案1】:

    responses library has a mechanism 允许使用 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')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 2015-06-26
      • 1970-01-01
      • 1970-01-01
      • 2013-05-11
      • 2016-06-08
      相关资源
      最近更新 更多