1

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.

Cerin
  • 60,957
  • 96
  • 316
  • 522

0 Answers0