I have a pytest fixture mocking multiple methods of an API client, using patch.multiple():
@pytest.fixture(scope='function', autouse=True)
def client_mock(request):    
    with patch.multiple(api_client,
                        method1=MagicMock(return_value=fixture1),
                        method2=MagicMock(return_value=fixture2),
                        method3=MagicMock(return_value=fixture3)) as mocks:
        yield mocks
This seems to work fine, however, when I try to access the mocks (by adding a client_mock parameter to a test function), I get an empty dictionary ({}). Why does it not contain any mocks?
patch.multiple does not return the values in the context manager if the mocks are already provided - only if you use the automatic creation of mocks using DEFAULT.
If you need to access the mocks in your tests, you can use DEFAULT and adapt the mocks after they are created:
from unittest.mock import patch, DEFAULT
@pytest.fixture(scope='function', autouse=True)
def client_mock():    
    with patch.multiple(api_client,
                        method1=DEFAULT,
                        method2=DEFAULT,
                        method3=DEFAULT) as mocks:
        mocks['method1'].return_value = fixture1
        mocks['method2'].return_value = fixture2
        mocks['method3'].return_value = fixture3
        yield mocks
or you can construct the mocks beforehand and create the returned dictionary yourself:
@pytest.fixture(scope='function', autouse=True)
def client_mock():
    mock1 = MagicMock(return_value=fixture1)
    mock2 = MagicMock(return_value=fixture2)
    mock3 = MagicMock(return_value=fixture3)
    with patch.multiple(api_client,
                        method1=mock1,
                        method2=mock2,
                        method3=mock3):
        yield {'method1': mock1, 'method2': mock2, 'method3': mock3}
The usual case is probably that you just want to patch the objects and don't need to access them in the tests. In this case you can just use:
@pytest.fixture(scope='function', autouse=True)
def client_mock(request):    
    with patch.multiple(api_client,
                        method1=MagicMock(return_value=fixture1),
                        method2=MagicMock(return_value=fixture2),
                        method3=MagicMock(return_value=fixture3)):
        yield
I agree that the documentation for this is not very clear, so that it may cause such misunderstandings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With