Mocking method with mock that accesses self

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.