Search code examples
pythonmockingpytestdecoratorfixtures

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


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?


Solution

  • 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