首页 > 解决方案 > Python Mock_requests:我可以在 Mocker 的 url 参数中使用通配符吗?与pytest一起使用时如何实现url的模式匹配?

问题描述

我编写了一个测试,试图模拟异常作为请求获取操作的副作用。我正在使用该requests_mock库,如下面的代码清单所示:

def test_owm_client_raises_error_for_timeout_error(owm_proxy: OWMProxy) -> None:
  
      with requests_mock.Mocker() as m:
          m.get(
              "http://api.openweathermap.org/geo/1.0/direct/*",
              exc=request_exceptions.Timeout,
          )
  
          city = "london"
          utc_now = datetime.now(timezone.utc)
          target_time = int((utc_now + timedelta(hours=10)).timestamp())
  
          with pytest.raises(APIException):
              owm_proxy.for_time(city, datetime.fromtimestamp(target_time).isoformat())

是否可以使用通配符参数模拟 url,例如http://api.openweathermap.org/geo/1.0/direct/*?到目前为止,我可以模拟模拟超时错误的预期效果的唯一方法是在模拟中使用requests.ANYurl 参数。

标签: pythonpytestrequests-mock

解决方案


通过re.compile()创建一个正则表达式模式,您可以将其输入到请求模拟程序中,如文档所示:

import re

import pytest
import requests
import requests_mock


def test_owm_client_raises_error_for_timeout_error():
      with requests_mock.Mocker() as m:
          # This is the regex pattern. Currently, it will accept any text after the base URL below. Update this if your requirements are stricter.
          matcher = re.compile('http://api.openweathermap.org/geo/1.0/direct/.*')

          # For simplicity, let's say we will just raise ValueError for the target URL
          m.get(
              matcher,
              exc=ValueError("Mocked error!"),
          )

          # Test if the exception ValueError will be raised if we accessed the target URLs
          with pytest.raises(ValueError):
            requests.get("http://api.openweathermap.org/geo/1.0/direct/")
          with pytest.raises(ValueError):
            requests.get("http://api.openweathermap.org/geo/1.0/direct/abcde")
          with pytest.raises(ValueError):
            requests.get("http://api.openweathermap.org/geo/1.0/direct/12345")
          with pytest.raises(ValueError):
            requests.get("http://api.openweathermap.org/geo/1.0/direct/abcde/12345")
          with pytest.raises(ValueError):
            requests.get("http://api.openweathermap.org/geo/1.0/direct/abcde/12345?any=thing&in=here")

          # Test if the mocked request wouldn't be used if the URL is different. Thus, the exception should show that the URL wasn't mocked.
          with pytest.raises(requests_mock.exceptions.NoMockAddress):
            requests.get("http://api.openweathermap.org/geo/1.0/direct2/")
          with pytest.raises(requests_mock.exceptions.NoMockAddress):
            requests.get("http://api.openweathermap.org/geo/1.0/direct2/abcde")

输出:

$ pytest -q
.
1 passed in 0.07s

推荐阅读