I am using the tenacity library to use its @retry
decorator.
I am using this to make a function which makes a HTTP-request \"repeat\" multiple times in
You can use unittest.mock module to mock some elements of tentacity library.
In your case all decorators you use are classes e.g. retry
is a decorator class defined here. So it might be little bit tricky, but I think trying to
mock.patch('tentacity.wait.wait_random_exponential.__call__', ...)
may help.
mock the base class wait func with:
mock.patch('tenacity.BaseRetrying.wait', side_effect=lambda *args, **kwargs: 0)
it always not wait
Thanks to discussion here, I found an elegant way to do this based on code from @steveb:
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(reraise=True, stop=stop_after_attempt(5), wait=wait_exponential(multiplier=1, min=4, max=10))
def do_something_flaky(succeed):
print('Doing something flaky')
if not succeed:
print('Failed!')
raise Exception('Failed!')
And tests:
from unittest import TestCase, mock, skip
from main import do_something_flaky
class TestFlakyRetry(TestCase):
def test_succeeds_instantly(self):
try:
do_something_flaky(True)
except Exception:
self.fail('Flaky function should not have failed.')
def test_raises_exception_immediately_with_direct_mocking(self):
do_something_flaky.retry.sleep = mock.Mock()
with self.assertRaises(Exception):
do_something_flaky(False)
def test_raises_exception_immediately_with_indirect_mocking(self):
with mock.patch('main.do_something_flaky.retry.sleep'):
with self.assertRaises(Exception):
do_something_flaky(False)
@skip('Takes way too long to run!')
def test_raises_exception_after_full_retry_period(self):
with self.assertRaises(Exception):
do_something_flaky(False)
The solution came from the maintainer of tenacity himself in this Github issue: https://github.com/jd/tenacity/issues/106
You can simply change the wait function temporarily for your unit test:
from tenacity import wait_none
func.retry.wait = wait_none()