Итак, вы определяете «повтор» как функцию. Затем вы определяете тест, затем вы определяете код, который использует @ retry.
@ retry в качестве декоратора вызывается во время импорта. Таким образом, порядок операций:
- объявить повтор
- объявить тест
- повторить вызов с retry_store_redis в качестве аргумента
- начать тест
- повторная попытка исправления
- вызов функции, которую вы определили на шаге 3
, поэтому «повтор» вызывается один раз (во время импорта), ваш макет вызывается ноль раз. Чтобы получить желаемое поведение (гарантируя, что повторная попытка фактически повторно вызывает базовую функцию), я бы сделал
@pytest.mark.asyncio
async def test_redis_failling(mocker):
fake_function = MagicMock(side_effect=ConnectionError)
decorated_function = retry(ConnectionError, initial_wait=2.0, attempts=5)(fake_function)
with pytest.raises(ConnectionError):
decorated_function()
assert fake_function.call_count == 4
, если бы вы хотели проверить это как построенное (вместо теста специально для декоратора) вам придется имитировать исходную функцию внутри декорированной функции, что будет зависеть от того, как вы реализовали декоратор. Способ по умолчанию (без каких-либо библиотек) означает, что вам нужно будет проверить атрибут «закрытие». Вы можете построить объект, чтобы сохранить ссылку на исходную функцию, хотя вот пример
def wrap(func):
class Wrapper:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
return Wrapper(func)
@wrap
def wrapped_func():
return 42
в этом сценарии вы можете исправить обернутую функцию на wrapped_func.func