Hello,
I’m writing a test where I need to replace a method with a mock implementation that does something with self. Here is a small example:
import unittest
import unittest.mock
class Pipeline:
def __init__(self):
self.a = 2
def very_expensive_method(self):
self.a = self.a ** 100
class TestPipeline(unittest.TestCase):
@unittest.mock.patch.object(Pipeline, 'very_expensive_method')
def test_very_expensive_method(self, mock_very_expensive_method):
def quick_method(self):
self.a = 3
mock_very_expensive_method.side_effect = quick_method
pipeline = Pipeline()
pipeline.very_expensive_method()
self.assertEqual(pipeline.a, 3)
This will fail with the error: TypeError: TestPipeline.test_very_expensive_method.<locals>.quick_method() missing 1 required positional argument: 'self'.
Because the Mock class doesn’t have an appropriate descriptor method they can’t be turned into bound methods.
I used autospec to work around this problem:
@unittest.mock.patch.object(Pipeline, 'very_expensive_method', autospec=True)
Internally autospec replaces the method not with a Mock but with a function that sort of behaves like a Mock and wraps the actual mock. Since the replacement is now a function it turned into a bound method as usual.
I was wondering if there is a better or more common way to solve this problem.