Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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'
like image 827
Aerophilic Avatar asked Jun 21 '16 15:06

Aerophilic


People also ask

What is monkeypatch in pytest?

monkeypatch can be used to patch functions dependent on the user to always return a specific value. In this example, monkeypatch. setattr is used to patch Path. home so that the known testing path Path("/abc") is always used when the test is run. This removes any dependency on the running user for testing purposes.

How do you write unit test cases in Python using pytest?

Writing unit tests using pytest To test with pytest we need to: Create a directory and put our test files inside it. Write our tests in files whose names start with test_ or end with _test.py . pytest will look for those files in the current directory and its subdirectories.

How do I run unit testing with pytest?

All you need to do is include a function with the test_ prefix. Because you can use the assert keyword, you don't need to learn or remember all the different self. assert* methods in unittest , either. If you can write an expression that you expect to evaluate to True , and then pytest will test it for you.

Can I use pytest and Unittest together?

pytest supports running Python unittest -based tests out of the box. It's meant for leveraging existing unittest -based test suites to use pytest as a test runner and also allow to incrementally adapt the test suite to take full advantage of pytest's features.


1 Answers

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.

like image 195
Li Feng Avatar answered Oct 22 '22 04:10

Li Feng