I don't understand why I can't do this operation when trying to mock time.sleep()
-- the sleep()
method will still delay the given time:
import unittest
from unittest.mock import patch
from time import sleep
class TestTime(unittest.TestCase):
@patch('time.sleep', return_value=None)
def test_time(self, mock_time):
sleep(10) # still delays 10s
if __name__ == '__main__':
unittest.main()
This works properly:
import unittest
from unittest.mock import patch
import time
class TestTime(unittest.TestCase):
@patch('time.sleep', return_value=None)
def test_time(self, mock_time):
time.sleep(10) # instant
if __name__ == '__main__':
unittest.main()
This results in an error TypeError: Need a valid target to patch. You supplied: 'sleep'
:
import unittest
from unittest.mock import patch
from time import sleep
class TestTime(unittest.TestCase):
@patch('sleep', return_value=None) # error
def test_time(self, mock_time):
sleep(10)
if __name__ == '__main__':
unittest.main()
Is there a proper way to mock sleep()
without needing to change all the modules I'm trying to test to use time.sleep()
?
My setup:
- Python version: 3.8.12
- OS: Windows 10 21H1 (19043.1766)
CodePudding user response:
The reason importing sleep
by name doesn't allow patch
to work in the examples is that patch
is looking for attribute names on an object in order to patch it. When importing by name, the object isn't provided and thus why there is a TypeError. The sleep
method is now in the namespace of the module importing it, so you can use that to properly patch sleep
.
To import sleep
by name and properly patch it, the following will work:
import unittest
from unittest.mock import patch
from time import sleep
class TestTime(unittest.TestCase):
@patch('__main__.sleep', return_value=None)
def test_time(self, mock_time):
sleep(10)
if __name__ == '__main__':
unittest.main()
As a caveat, if you have a module named my_module
that uses from time import sleep
and a separate file for tests, you can do the following within the test file to patch sleep
within my_module
:
@patch('my_module.sleep', return_value=None)