Is it possible to write a function-level pytest fixture that applies a mock decorator to the function?

Viewed 553

In our repo, we have some calls to s3. We never want these to execute during testing, so we mock them out in each individual test, which gets annoying. It's a lot of repeated code, and can be dangerous if a developer forgets to write the mock before running the test.

I would like to write a pytest fixture that automatically applies the mock to every testing function. That is, I want to change my code from looking like this:

test_file.py:

@mock.patch.object(S3Hook, 'write_to_s3')
def test1(_):
    # test some stuff without writing to s3

@mock.patch.object(S3Hook, 'write_to_s3')
def test2(_):
    # test some more stuff without writing to s3

to this:

conftest.py:

@pytest.fixture(scope='function', autouse=True)
def mock_out_s3(request):
    # somehow apply the mock.patch.object decorator to request.function here


test_file.py:

def test1():
    # test some stuff; the mock is automatically applied, so we won't write to s3

def test2():
    # ditto

Is this possible?

2 Answers

Posting the details of how I got this to work (based on ParthS007's answer) to help out anyone else who is trying to do the same thing in the future:

@pytest.fixture(scope='function', autouse=True)
def mock_out_s3(request):
    patcher = mock.patch.object(S3Hook, 'write_to_s3')
    patcher.start()
    request.addfinalizer(patcher.stop)

While writing these Unittests. You can do this:


Class TestClass(TestCase):

    @classmethod
    def setUpTestData(cls):
        pass

    def tearDown(self):
        self.patcher.stop()

    def setup(self):
       self.patcher = mock.patch(S3Hook, 'write_to_s3')
       mock_apply = self.patcher.start()

    def test1(self):
    # test some stuff; the mock is automatically applied, so we won't write to s3

    def test2(self):
    # ditto


You can find more detail about the patcher here: https://docs.python.org/3/library/unittest.mock.html#the-patchers

Related