pytestmonkeypatchingpytest-mock

How to mock imported module class in pytest


I have this files.

I'd like to use mocking_util.py instead of util.py in test code.

I know mocker.patch("util.my_something1", return_value = 1) but it only works at function level.

How can I mock an entire module?

main.py

from . import util.py

def something1(a, b):
    return util.my_something(a, b)

def something2(a, b):
    return util.my_something2(a, b)

def something3(a, b):
    return util.my_something3(a, b)

util.py

def my_something1(a, b):
    return a + b

def my_something2(a, b):
    return a + b + 1

def my_something3(a, b):
    return a + b + 2

mocking_util.py

def my_something1(a, b):
    return 1

def my_something2(a, b):
    return 1

def my_something2(a, b):
    return 1

test_main.py

import main

def test_case1(mocker):
    # I'd like to use mocking_util.py instead of util.py
    # What should I do for this?

    result = main.something1(10, 10)
    assert result == 1

    result = main.something2(10, 10)
    assert result == 1

    result = main.something3(10, 10)
    assert result == 1

Solution

  • Using pytest-mock

    pip install pytest-mock

    Patch the util module in the main module with mocking_util

    import main
    import mocking_util
    
    
    def test_case1(mocker):
        
        mocker.patch('main.util', mocking_util)
    

    The mocker fixture allows you to access the unittest.mock.patch symbol.

    unittest.mock.patch(target, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)

    The target is imported and the specified object replaced with the new object [passed in new].

    Now when main calls util.my_something, it will call mocking_util.my_something

        
        result = main.something1(10, 10)
        assert result == 1
    
        result = main.something2(10, 10)
        assert result == 1
    
        result = main.something3(10, 10)
        assert result == 1