How do you make Python's unittest.mock.patch
return an object that lets you assign a callable return value?
For example, I have a custom class in myclass.py
defined as:
class MyClass:
@property
def someprop(self):
return 'you should never see this in a test'
I want to test a function that acts on data retrieved from someprop
. In my real application, someprop
actually calls some complicated external database that's not accessible in a unittest, and isn't really necessary for the purposes of the unittest, so I decide to mock a return value using the patch
and the faker
package.
So my unittest looks like:
import unittest
import unittest.mock
from faker import Faker
from myclass import MyClass
class Tests(unittest.TestCase):
@unittest.mock.patch('myclass.MyClass.someprop')
def test_mock_error(self, mock_myclass_someprop):
class RandomText:
@property
def text(self):
factory = Faker()
return factory.text()
# Make calls to someprop return random text.
mock_myclass_someprop.return_value = RandomText.text
a = MyClass()
actual_text = a.someprop
print('actual text:', actual_text)
self.assertTrue('MagicMock' not in str(actual_text)) # this fails
if __name__ == '__main__':
unittest.main()
Every time the test runs, the patch causes it to access the text
property on my RandomText
instance instead of someprop
, which should return a unique string. However, this fails because the mock is actually returning a value like <MagicMock name='someprop' id='140126618001360'>
.
Why is this, and how do I fix it?
I've tried refactoring how I set and call return_value
, but no matter what I do, it returns a MagicMock
instance instead of a real return value retrieved from my patched callable.