Home > OS >  Set Pytest mock value to None
Set Pytest mock value to None

Time:02-21

I have a main.py file which includes WindoMgr class, xvfb as a class attibute and two classmethods: _cleanup_lock_file and func_to_test. I only have problem with testing else block, which gets triggered when cls.xvfb is None. The else block returns default value of b which is 1.

#main.py
class WindowMgr:
    xvfb = None

    @classmethod
    def _cleanup_lock_file(cls):
        return True

    @classmethod
    def func_to_test(cls):
        b = 1
        if cls.xvfb is not None:
            print(cls.xvfb)  #<MagicMock name='xvfb' id='61908568'>
            try:
                cls.xvfb.terminate()
                b = 2
            except Exception:
                b = 1   2
            finally:
                cls._cleanup_lock_file()
        else:
            return b
        return b

Now, in the test_main.py file, I have patched the xvfb to mock cls.xvfb.terminate() in try block, but I want cls.xvfb to be None for the else block to be triggered. I have tried something like xvfb = None or xvfb.return_value = None. But the else block doesn't get triggered as printing cls.xvfb shows it as a MagickMock object as commented out in the code. The WindowMgr.func_to_test() return value is 2 and not 1. It should return default value of b as 1. How do I set cls.xvfb mock object as None? Any help would be appreciated.

#test_main.py
from main import WindowMgr

def test_main_func(mocker):
    xvfb = mocker.patch.object(WindowMgr, 'xvfb')

    # To test the else block
    # xvfb = None -----> doesn't work
    # xvfb.return_value = None ----> doesn't work

    assert WindowMgr.func_to_test() == 1   # AssertionError: assert 2 == 1

CodePudding user response:

The problem is that setting xvbf does only reassign the local variable, not the mocked variable (this is just normal Python behavior). Setting the return_value does not work, because xvbf is not a callable. However, if you use a property mock instead of a regular mock, it will behave as if it were a callable, and the value can be set via return_value:

def test_main_func(mocker):
    xvfb = mocker.patch.object(WindowMgr, "xvfb",
                               new_callable=mocker.PropertyMock)
    xvfb.return_value = None

    assert WindowMgr.func_to_test() == 1

(you can access PropertyMock directly from mocker as a convenience)

Even if xvbf is a class variable and not a property, it behaves like a property from the perspective of a mock and this will work.

  • Related