【问题标题】:Conditionally mock httputil.get method on specific url with path json使用路径 json 有条件地在特定 url 上模拟 httputil.get 方法
【发布时间】:2021-08-04 21:30:40
【问题描述】:

我已经模拟了 http get 方法,以便在不实际发送 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() 方法。

如何同时使用这两种方法,以便一方面可以使用条件,另一方面可以轻松地模拟响应?

【问题讨论】:

    标签: python unit-testing http mocking patch


    【解决方案1】:

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

    您可以模拟特定的网址:

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

    你也可以exclude other urls:

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

    【讨论】:

      猜你喜欢
      • 2021-07-17
      • 2020-12-10
      • 2019-05-25
      • 2021-12-17
      • 2020-08-08
      • 2014-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多