首页 > 解决方案 > 使用路径 json 有条件地在特定 url 上模拟 httputil.get 方法

问题描述

我已经模拟了 httpget方法,以便在不实际发送 url 的情况下从 url 获取响应:

def get(url, retries=None, back_off_factor=None, max_back_off=None, timeout=None, response_encoding=None,
        retry_on_timeout=None, retry_codes=None, **kwargs):
    return _make_request("GET", url,
                         retries=retries, back_off_factor=back_off_factor,
                         max_back_off=max_back_off,
                         timeout=timeout,
                         response_encoding=response_encoding,
                         retry_on_timeout=retry_on_timeout,
                         retry_codes=retry_codes,
                         **kwargs)
@patch('lib.httputil.get')
    def test_harvest(self, mock_get):
        articles = json.load(json_file)

        # Configure the mock to return a response with an OK status code. Also, the mock should have
        # a `json()` method that returns a list of todos.
        mock_get.return_value = Mock(ok=True)
        mock_get.return_value.json.return_value = articles
        mock_get.return_value.status_code = 200


        the_rest_of_the_test()

但我意识到只有当 URL 是特定的时我才需要模拟它。我知道我可以使用new关键字并执行以下操作:

    def mock_get(self, url):
        if url == MY_SPECIFIC_URL:
            {...}
        else:
            self.old_get(url)


{...}

 with mock.patch('portality.lib.httputil.get', new=self.mock_get):
    the_rest_of_the_test()

但我真的不知道如何模拟 Response 对象,以便它返回正确的状态代码并为.json()方法提供正确的结果。

我怎样才能同时使用这两种方法,以便一方面我可以使用条件但另一方面以简单的方式模拟响应?

标签: pythonunit-testinghttpmockingpatch

解决方案


我建议您使用requests库以及专门用于返回所需 HTTP 响应的响应

您可以模拟特定的网址:

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"}'

您可以排除其他网址

responses.add_passthru(re.compile('https://percy.io/\\w+'))

推荐阅读