I have written a test that tries to mock an exception as a side effect of a requests get operation. I am using the requests_mock
library as shown in the code listing below:
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())
Is it possible to mock a url using wildcard parameters, e.g. http://api.openweathermap.org/geo/1.0/direct/*
? So far, the only way that I can simulate the desired effect of mocking a Timeout error is using requests.ANY
as the url parameter in the mock.
Create a regex pattern via re.compile() which you can input to the requests mocker as documented:
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")
Output:
$ pytest -q
.
1 passed in 0.07s