我试图使用python模拟包来模拟python请求模块。让我在下面的场景中工作的基本调用是什么?

在views.py中,我有一个函数,它每次都以不同的响应进行各种request .get()调用

def myview(request):
  res1 = requests.get('aurl')
  res2 = request.get('burl')
  res3 = request.get('curl')

在我的测试类中,我想做类似的事情,但不能确定确切的方法调用

步骤1:

# Mock the requests module
# when mockedRequests.get('aurl') is called then return 'a response'
# when mockedRequests.get('burl') is called then return 'b response'
# when mockedRequests.get('curl') is called then return 'c response'

步骤2:

调用我的视图

步骤3:

验证响应包含'a response', 'b response', 'c response'

我如何完成第1步(模拟请求模块)?


当前回答

以下是对我有效的方法:

import mock
@mock.patch('requests.get', mock.Mock(side_effect = lambda k:{'aurl': 'a response', 'burl' : 'b response'}.get(k, 'unhandled request %s'%k)))

其他回答

这就是模拟请求的方法。Post,将其更改为HTTP方法

@patch.object(requests, 'post')
def your_test_method(self, mockpost):
    mockresponse = Mock()
    mockpost.return_value = mockresponse
    mockresponse.text = 'mock return'

    #call your target method now

以下是对我有效的方法:

import mock
@mock.patch('requests.get', mock.Mock(side_effect = lambda k:{'aurl': 'a response', 'burl' : 'b response'}.get(k, 'unhandled request %s'%k)))

对于pytest用户,有一个来自https://pypi.org/project/pytest-responsemock/的方便的fixture

例如,模拟GET到http://some.domain,你可以:

def test_me(response_mock):

    with response_mock('GET http://some.domain -> 200 :Nice'):
        response = send_request()
        assert result.ok
        assert result.content == b'Nice'

这对我来说是可行的,尽管我还没有做太多复杂的测试。

import json
from requests import Response

class MockResponse(Response):
    def __init__(self,
                 url='http://example.com',
                 headers={'Content-Type':'text/html; charset=UTF-8'},
                 status_code=200,
                 reason = 'Success',
                 _content = 'Some html goes here',
                 json_ = None,
                 encoding='UTF-8'
                 ):
    self.url = url
    self.headers = headers
    if json_ and headers['Content-Type'] == 'application/json':
        self._content = json.dumps(json_).encode(encoding)
    else:
        self._content = _content.encode(encoding)

    self.status_code = status_code
    self.reason = reason
    self.encoding = encoding

然后你可以创建响应:

mock_response = MockResponse(
    headers={'Content-Type' :'application/json'},
    status_code=401,
    json_={'success': False},
    reason='Unauthorized'
)
mock_response.raise_for_status()

给了

requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: http://example.com

尝试使用响应库。以下是他们文档中的一个例子:

import responses
import requests

@responses.activate
def test_simple():
    responses.add(responses.GET, 'http://twitter.com/api/1/foobar',
                  json={'error': 'not found'}, status=404)

    resp = requests.get('http://twitter.com/api/1/foobar')

    assert resp.json() == {"error": "not found"}

    assert len(responses.calls) == 1
    assert responses.calls[0].request.url == 'http://twitter.com/api/1/foobar'
    assert responses.calls[0].response.text == '{"error": "not found"}'

相比于自己设置所有的mock,它提供了相当好的便利。

还有HTTPretty:

它不是特定于请求库,在某些方面更强大,尽管我发现它不太适合检查它拦截的请求,而响应则很容易

还有httmock。

最近,一个比古老的请求更受欢迎的新库是httpx,它增加了对异步的一等支持。httpx的模拟库是:https://github.com/lundberg/respx