Search code examples
pythonpython-3.xunit-testingmockingpolling

How can I mock waiting library in Python?


I'm using the waiting library in some of my code to wait for a condition to become true. As a part of the library, waiting.wait returns True when the predicate is true; otherwise it throws and exception or waits forever depending on timeout values, etc.

I'd like to patch this in my tests to always return True without getting into the wait cycle. Here's my attempt:

#!/usr/bin/env python3

from unittest.mock import Mock
import waiting
from waiting import wait

def test_waiting():
    waiting.wait.return_value = True
    # Below *should* wait forever because it can never be true.
    # Want to make it return true instead.
    return wait(lambda: False)

if __name__ == "__main__":
    assert(test_waiting())

What I find, though, is that it actually calls the library's code instead of short-circuiting the return.

How can I force this method to simply return a value (or raise a side-effect) without actually calling the code?


Solution

  • Your waiting.wait.return_value = True won't work, because waiting.wait is not a mock object. You only added an arbitrary attribute to the existing wait function, but that function won't use that attribute.

    To mock out the wait function, just mock it directly:

    from unittest import mock
    
    with mock.patch('__main__.wait'):
        wait.return_value = True
    

    There is no need to mock the internals of the waiting library, all you want to happen in your code is that any use of the wait() callable immediately returns.

    Note that I picked the __main__ module to patch the name wait() in, see Where to patch in the unittest.mock documentation.

    Your actual location may differ, and if you used import waiting everywhere, then you'd have to use mock.patch('waiting.wait'). Otherwise, you generally would apply it the same module you used from waiting import wait in.