Aerophilic
Aerophilic

Reputation: 885

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'

Upvotes: 8

Views: 7144

Answers (1)

Li Feng
Li Feng

Reputation: 1021

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.

Upvotes: 8

Related Questions