Search code examples
pythonunit-testingpytestmonkeypatching

How to use monkeypatch in a "setup" method for unit tests using pytest?


I am attempting to mock out a utility class (In this case the python logger utility) in a unit test.

While I know how to do it using monkeypatch on a per test level, I was hoping I could simply do it as part of the setup/globally in some way.

Here is what I am hoping I can do (but I am getting errors):

import logging

...

def setup(self, monkeypatch):

    class fake_logger(level):
        def __init__(self, val):
            pass

        def setLevel(self, level):
            # Do something

    def mock_logger(level):
        return fake_logger(level)
    monkeypatch.setattr(logging, 'getLogger', mock_logger)

What is the right way to do this?

EDIT: Example error

name = 'setup'

def call_optional(obj, name):
    method = getattr(obj, name, None)
    isfixture = hasattr(method, "_pytestfixturefunction")
    if method is not None and not isfixture and py.builtin.callable(method):
        # If there's any problems allow the exception to raise rather than
        # silently ignoring them
>           method()
E           TypeError: setup() missing 1 required positional argument: 'monkeypatch'

Solution

  • monkeypatch works as a normal pytest fixture. If you want to use it, you need to make your method as a fixture as well.

    import logging
    
    import pytest
    
    
    @pytest.fixture
    def setup(monkeypatch):
    
        class fake_logger(object):
            def __init__(self, val):
                pass
    
            def setLevel(self, level):
                # Do something
                pass
    
        def mock_logger(level):
            return fake_logger(level)
        monkeypatch.setattr(logging, 'getLogger', mock_logger)
    
    def test_fake_logger(setup):
        # test steps
    

    and if you check the type of logging.getLogger('any level') in test, it will be fake_logger you defined.