Mocking function within a function pytest?
Asked Answered
N

2

10
def func1():
    return 5
    
def func2(param1, param2):
    
    var1 = func1()
    return param1 + param2 + var1

I want to use pytest to test the second function by mocking the first, but I am not sure how to do this.

@pytest.fixture(autouse=True)
def patch_func1(self):
    with mock.patch(
        "func1",
        return_value= 5,
    ) as self.mock_func1:
        yield

I think it can be done with a dependency injection and fixture as above but that would mean changing func1 which I would prefer not to do.

Nations answered 11/7, 2022 at 18:23 Comment(1)
If those functions are in the same module, as shown, don't mock anything - that's an implementation detail. Assert on the overall return of func2, e.g. assert func2(2, 2) == 9. That way you can refactor confidently within the module boundary and your tests remain useful.Congeneric
A
11

You don't need to change anything.

You can use mocker fixture with pytest (requires installation of pytest-mock). don't worry about the mocker argument, it will magically work.

def test_func2(mocker):
    mocked_value = 4
    first = 1
    second = 2
    func1_mock = mocker.patch("func1")
    func1_mock.return_value = mocked_value
    actual_value = func2(first, second)
    assert actual_value == first + second + mocked_value
Azimuth answered 11/7, 2022 at 19:8 Comment(1)
I was not aware of pytest-mock thanks !Nations
C
0

An alternative to pytest-mock that uses built-in fixture of pytest instead of a separate package is the monkeypatch fixture.

from my_module import func2


def test_func2(monkeypatch):
    mocked_value = 4
    # create a function that returns the desired mock value
    def mock_func_1():
        return mocked_value
    # patch the module with the mocked function
    monkeypatch.setattr(my_module, "func1", mock_func_1)
    first = 1
    second = 2
    actual_value = func2(first, second)
    assert actual_value == first + second + mocked_value

One difference I've heard mentioned between pytest-mock and monkeypatch is that monkeypatch allegedly changes the behavior of the mocked function globally within the test environment during runtime, whereas pytest-mock does so only within the scope of an individual test. If that were true it would be a potential gotcha and a reason to prefer pytest-mock. But I have not seen this to be the case. The monkeypatched function has to be patched in each test and is not a global patch. This is good because you don't want stateful interdependencies between your unit tests. A reason to prefer monkeypatch, on the other hand, is to avoid adding additional dependencies to your code base that add to your maintenance burden.

Citron answered 30/7, 2024 at 16:33 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.