Jora
Jora

Reputation: 35

How can I mock external function that is used in class method?

I want to mock a function that is used in some method. This function is located in other module.

How can I do that?

Tried this option, but it does not work.

from pack import utils
from pack.another_pack import SomeClass

@pytest.mark.parametrize('attr', ['a', 'b', 'c'])
def test_foo_bar(attr, monkeypatch):
    def mock_return():
        return attr
    monkeypatch.setattr(utils, 'my_function', mock_return)
    SomeClass().foo()  # this foo() function uses my_function inside that I want to mock

I want SomeClass().foo() to execute my mock_return() inside instead of my_function().

Upvotes: 0

Views: 4853

Answers (1)

Alexander Fasching
Alexander Fasching

Reputation: 621

You can use unittest.mock.patch or the pytest-mock plugin with the mocker fixture.

Your package

pack/another_pack.py:

from pack import utils

class SomeClass:
    def foo(self):
        return utils.my_function()

pack/utils.py:

def my_function():
    return 'original'

Tests

import pytest
from unittest.mock import patch
from pack.another_pack import SomeClass


# Replace my_function with another function. You could pass parameters
# to the mocked function and handle them in the replacement.
@pytest.mark.parametrize("attr", ["a", "b", "c"])
def test_replace(attr):
    def mock_return():
        return attr

    with patch("pack.another_pack.utils.my_function", new=mock_return):
        assert SomeClass().foo() == attr


# If you just want to override the return value.
@pytest.mark.parametrize("attr", ["a", "b", "c"])
def test_return_value(attr):
    with patch("pack.another_pack.utils.my_function") as my_func:
        my_func.return_value = attr
        assert SomeClass().foo() == attr


# With the pytest-mock plugin and the mocker fixture instead of unittest.mock.
@pytest.mark.parametrize("attr", ["a", "b", "c"])
def test_mock_plugin(attr, mocker):
    my_func = mocker.patch("pack.another_pack.utils.my_function")
    my_func.return_value = attr
    assert SomeClass().foo() == attr

Note that in all tests the first argument of patch is the name of the module where you want to mock the function (pack.another_pack) with the name of the function how it appears in the module (utils.my_function).

my_function is mocked for the entire pack.another_pack module.

Upvotes: 3

Related Questions