Skip to content

Differences in using retry with AsyncMock objects on Python 3.9 and Python 3.8 vs. newer Python #456

Open
@MatthewFlamm

Description

@MatthewFlamm

I'm trying to write a test using AsyncMock object with a side_effect error that is then wrapped with tenacity.retry. In Python 3.10+, my tests work, but in Python 3.8 and Python 3.9 the side effect is not swallowed by retry. See below for a MRE.

from unittest.mock import AsyncMock
from tenacity import retry

async def test_mock_retry():

    amock = AsyncMock()
    amock.side_effect = [ValueError, None]

    retry_func = retry(amock)
    await retry_func()
    
    assert amock.call_count == 2

This passes on Python 3.10, Python 3.11, and Python 3.12 but fails on Python 3.8 and Python 3.9 for me.

traceback from Python 3.9:

_______________________________ test_mock_retry ________________________________

    async def test_mock_retry():
    
        amock = AsyncMock()
        amock.side_effect = [ValueError, None]
    
        retry_func = retry(amock)
>       await retry_func()

tests/test_async_mock.py:10: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <AsyncMock id='140142953906240'>, args = (), kwargs = {}, _call = call()
effect = <list_iterator object at 0x7f7593046850>, result = <class 'ValueError'>

    async def _execute_mock_call(self, /, *args, **kwargs):
        # This is nearly just like super(), except for special handling
        # of coroutines
    
        _call = _Call((args, kwargs), two=True)
        self.await_count += 1
        self.await_args = _call
        self.await_args_list.append(_call)
    
        effect = self.side_effect
        if effect is not None:
            if _is_exception(effect):
                raise effect
            elif not _callable(effect):
                try:
                    result = next(effect)
                except StopIteration:
                    # It is impossible to propogate a StopIteration
                    # through coroutines because of PEP 479
                    raise StopAsyncIteration
                if _is_exception(result):
>                   raise result
E                   ValueError

/usr/local/lib/python3.9/unittest/mock.py:2162: ValueError

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions