pytest provides a fixture for this use-case: monkeypatch.syspath_prepend.

You may prepend a path to sys.path list of import locations. Write a fake fwlib.py and include it in your tests, appending the directory as necessary. Like the other test modules, it needn't be included with the distribution.

After playing with this myself, I couldn't actually figure out how to get the fixture to mock module level imports correctly from the library code. By the time the tests run, the library code was already imported and then it is too late to patch.

However, I can offer a different solution that works: you may inject the name from within conftest.py, which gets imported first. The subsequent import statement within the code under test will just re-use the object already present in sys.modules.

Package structure:

$ tree .
.
├── conftest.py
├── lib
│   └── my_lib.py
└── tests
    └── test_my_lib.py

2 directories, 3 files

Contents of files:

# conftest.py
import sys

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

module = type(sys)('fwlib')
module.sum = fwlib_sum
sys.modules['fwlib'] = module

library file:

# lib/my_lib.py
import fwlib

def fw_sum(a, b):
    return fwlib.sum(a, b)

test file:

# lib/test_my_lib.py
import my_lib

def test_sum():
    assert my_lib.fw_sum(1, 2) == 3
Answer from wim on Stack Overflow
Top answer
1 of 3
56

pytest provides a fixture for this use-case: monkeypatch.syspath_prepend.

You may prepend a path to sys.path list of import locations. Write a fake fwlib.py and include it in your tests, appending the directory as necessary. Like the other test modules, it needn't be included with the distribution.

After playing with this myself, I couldn't actually figure out how to get the fixture to mock module level imports correctly from the library code. By the time the tests run, the library code was already imported and then it is too late to patch.

However, I can offer a different solution that works: you may inject the name from within conftest.py, which gets imported first. The subsequent import statement within the code under test will just re-use the object already present in sys.modules.

Package structure:

$ tree .
.
├── conftest.py
├── lib
│   └── my_lib.py
└── tests
    └── test_my_lib.py

2 directories, 3 files

Contents of files:

# conftest.py
import sys

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

module = type(sys)('fwlib')
module.sum = fwlib_sum
sys.modules['fwlib'] = module

library file:

# lib/my_lib.py
import fwlib

def fw_sum(a, b):
    return fwlib.sum(a, b)

test file:

# lib/test_my_lib.py
import my_lib

def test_sum():
    assert my_lib.fw_sum(1, 2) == 3
2 of 3
10

Just to provide a little more details to @wim's good answer, you can use it with submodules too, like so:

import sys
module = type(sys)("my_module_name")
module.submodule = type(sys)("my_submodule_name")
module.submodule.something = sommething
sys.modules["my_module_name"] = module
sys.modules["my_module_name.my_submodule_name"] = module.submodule
🌐
PyPI
pypi.org › project › pytest-mock
pytest-mock · PyPI
pip install pytest-mock Copy PIP instructions · This plugin provides a mocker fixture which is a thin-wrapper around the patching API provided by the mock package: import os class UnixFS: @staticmethod def rm(filename): os.remove(filename) def test_unix_fs(mocker): mocker.patch('os.remove') UnixFS.rm('file') os.remove.assert_called_once_with('file') Besides undoing the mocking automatically after the end of the test, it also provides other nice utilities such as spy and stub, and uses pytest introspection when comparing calls.
Discussions

How to mock individual functions from an imported module with individual return values?
No. In this case you would patch them inside module_to_import, not module_to_test. This is described in the "Where to patch" section of the unittest.mock documentation: However, consider the alternative scenario where instead of from a import SomeClass module b does import a and some_function uses a.SomeClass. Both of these import forms are common. In this case the class we want to patch is being looked up in the module and so we have to patch a.SomeClass instead: More on reddit.com
🌐 r/learnpython
2
2
May 1, 2023
python - How to mock a imported object with pytest-mock or magicmock - Stack Overflow
I am trying to understand the mock/monkeypatch/pytest-mock capabilities. Let me know if this is possible. If not could you please suggest how I can test this code. My code structure: / ./app ../ More on stackoverflow.com
🌐 stackoverflow.com
python - Mocking an imported function with pytest - Stack Overflow
No it won't. I tried importing from cars.lib.email import send_email and then send_email = MagicMock() in the test file but it also gets not called error. ... I know I have misunderstood how mocking works. I'm just not sure 'where' I should be mocking. ... Since you are using pytest, I would ... More on stackoverflow.com
🌐 stackoverflow.com
python - Pytest with mock/pytest-mock - Stack Overflow
For some reason I cannot get mock.patch to work in any scenario when using Pytest. It simply doesn't do the patching. Am I using it incorrectly or is something messed up with my configuration? ... import pytest import mock from pytest_mock import mocker from base import get_foo @mock.patch... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Medium
medium.com › bungalow-garage › mocking-dependencies-in-a-python-module-6bb82c2c7ce9
Mocking dependencies in a Python module | by Kellen Steffen | Bungalow Garage | Medium
May 21, 2019 - At Bungalow, we use pytest-mock, which provides a thin wrapper around unittest.mock as a keyword arg called mocker to each test function. I referred to the official mock docs, including the “Where to patch” section, to see how to mock a function in an imported dependency, but the examples only cover class mocking.
🌐
GitHub
github.com › pytest-dev › pytest-mock
GitHub - pytest-dev/pytest-mock: Thin-wrapper around the mock package for easier use with pytest · GitHub
import os class UnixFS: @staticmethod def rm(filename): os.remove(filename) def test_unix_fs(mocker): mocker.patch('os.remove') UnixFS.rm('file') os.remove.assert_called_once_with('file') Besides undoing the mocking automatically after the end of the test, it also provides other nice utilities such as spy and stub, and uses pytest introspection when comparing calls.
🌐
GitHub
github.com › pytest-dev › pytest-mock › blob › main › tests › test_pytest_mock.py
pytest-mock/tests/test_pytest_mock.py at main · pytest-dev/pytest-mock
from unittest.mock import MagicMock · · import pytest · · from pytest_mock import MockerFixture · from pytest_mock import PytestMockWarning · from pytest_mock import SpyType · · pytest_plugins = "pytester" · # could not make some of the tests work on PyPy, patches are welcome!
Author: pytest-dev
🌐
OneUptime
oneuptime.com › home › blog › how to use pytest with mocking
How to Use pytest with Mocking
February 2, 2026 - Install it alongside pytest. ... The Mock class creates objects that record how they are used and can be configured to return specific values. Here is a simple example showing how Mock objects work. # Understanding Mock objects and their behavior from unittest.mock import Mock # Create a mock object that can pretend to be anything mock = Mock() # Mock objects accept any attribute access or method call mock.some_method() # Does not raise an error mock.any_attribute # Returns another Mock object mock.nested.deeply.call() # Still works # Configure what the mock returns mock.get_user.return_value = {"name": "Alice", "id": 1} # Now calling get_user returns our configured value result = mock.get_user() print(result) # {"name": "Alice", "id": 1} # Mock tracks all calls made to it mock.get_user.assert_called_once() # Passes mock.get_user.assert_called_with() # Passes (no arguments)
🌐
Readthedocs
pytest-mock.readthedocs.io
pytest-mock documentation
This pytest plugin provides a mocker fixture which is a thin-wrapper around the patching API provided by the mock package: import os class UnixFS: @staticmethod def rm(filename): os.remove(filename) def test_unix_fs(mocker): mocker.patch('os.remove') UnixFS.rm('file') os.remove.assert_called_once_with('file') Besides undoing the mocking automatically after the end of the test, it also provides other nice utilities such as spy and stub, and uses pytest introspection when comparing calls.
Find elsewhere
🌐
Reddit
reddit.com › r/learnpython › how to mock individual functions from an imported module with individual return values?
r/learnpython on Reddit: How to mock individual functions from an imported module with individual return values?
May 1, 2023 -

I have a file module_to_import.py...

def function_1(foo):
    return 'bar' # actual return value isn't just a constant

def function_2(bar):
    return 'baz' # actual return value isn't just a constant

...and another file module_to_test.py which imports the previous module and calls its functions inside a class...

import module_to_import

class MyClass:

    def method(self):
        foo = ...
        bar = module_to_import.function_1(foo)
        baz = module_to_import.function_2(bar)
        return baz

My goal is to write a test for MyClass.method.

All that method does is call other functions/methods. Those functions/methods already have their own tests. So to test only MyClass.method with no confounding side effects, I'd like to simply mock all the objects that get called inside its body, and test only that those objects are called as expected.

But to do this properly with maximum control, I'll need to mock the return values for each object. Given that the entire module_to_import.py is imported, rather than its functions individually, I'm not quite sure how to do this...

If the functions were imported individually, ...

# module_to_test.py

from module_to_import import function_1, function_2

class MyClass:

    def method(self):
        foo = ...
        bar = function_1(foo)
        baz = function_2(bar)
        return baz

...then it would be as simple as patching them directly from within the namespace of module_to_test...

from unittest.mock import Mock, patch

class TestMyClass:

    def test_method(self):
        mock_function_1_retval = 'bar'
        mock_function_2_retval = 'baz'
        with (
            patch('module_to_test.function_1', return_value=mock_function_1_retval) as mock_function_1,
            patch('module_to_test.function_2', return_value=mock_function_2_retval) as mock_function_2
        ):
            baz = my_class.method()
        mock_function_1.assert_called_once_with('foo')
        mock_function_2.assert_called_once_with('bar')

But as things are, to access function_1 and function_2, I have to do so through their shared namespace module_to_test.module_to_import, e.g.

from unittest.mock import Mock, patch

class TestMyClass:

    def test_method(self):
        with patch('module_to_test.module_to_import') as mock_module_to_import:
            bar = my_class.method()
        # somehow assert `mock_module_to_import.function_1` called with `'foo'`
        # somehow assert `mock_module_to_import.function_2` called with `'bar'`

In that case, I'm unsure how to give the functions different return values.

Can anyone weigh in here? Maybe it's obvious and I'm just approaching this from the wrong angle...

🌐
Chang Hsin Lee
changhsinlee.com › pytest-mock
pytest: How to mock in Python - Chang Hsin Lee
May 2, 2020 - If you have trouble understanding mocks for testing in Python like me, then this post is for you. ... Both can be installed via pip. ... Here’s an example. Imagine that you have a function called compute(). Part of its code contains an expensive_api_call() that takes 1,000 seconds to run · import time def compute(x): response = expensive_api_call() return response + x def expensive_api_call(): time.sleep(1000) # takes 1,000 seconds return 123
🌐
Uadnan
uadnan.com › articles › mocking-imports-in-python-for-unittesting
Mocking Imports in Python for Unit Testing: A Comprehensive Guide | Adnan Umer
April 2, 2023 - This blog post provides a comprehensive guide on how to mock imports in Python for unit testing. It covers the use of sys.modules dictionary and MagicMock objects to replace real modules with mock objects, and provides examples for both pytest and unittest frameworks.
🌐
Medium
medium.com › @bfortuner › python-unit-testing-with-pytest-and-mock-197499c4623c
Python unit testing with Pytest and Mock | by Brendan Fortuner | Medium
June 1, 2017 - python -m pytest tests/ (all tests) ... tests/ (print output to console) Import statements · import · mock import pytest from pytest_mock import mocker from src.jobitems import manager ·...
🌐
Physics Forums
physicsforums.com › other sciences › programming and computer science
Pytest, unittest : Mocking out a non-existent imported module • Physics Forums
July 9, 2022 - The user demonstrates how to mock the missing module 'a_missing_module' in the 'provider.py' file by directly assigning a Mock object to 'sys.modules'. The solution highlights that when importing a specific function from a module, a full dotted path is unnecessary for mocking.
Top answer
1 of 4
5

I believe you are right not testing cases on a real database because it's not unit testing anymore if you are using external dependencies.

There is a possibility to specify return-value and customize it (different return values on each iteration even) for Mock or MagicMock objects.

from unittest.mock import Mock, patch 

from app import db_conn


@patch('app.db_conn.find')
def test_some_func1(db_con_mock):
    ...
    assert ...

Keep in mind that in each patch you should specify the import path of db_conn - the path where db_conn **is used (I assume it's a different path in each test), not where it is defined.

2 of 4
3

To answer the intial question "How to mock a imported object with pytest-mock or magicmock" you can do:

from unittest import mock  # because unittest's mock works great with pytest

def test_some_func1():
    with mock.patch('some_module1.db', mock.MagicMock(return_value=...)) as magicmock:
        result = some_func1(...)
        assert ... e.g. different fields of magicmock
        assert expected == result

# or alternatively use annotations

@mock.patch('some_module2.db', mock.MagicMock(return_value=...))
def test_some_func2():
        result = some_func2(...)

note that you do not patch the actual source of db

For your other use case

I want to mock the database (using a mongo database), more specifically the "db_conn" object

you similarly follow the hints of the link above:

mock.patch('some_module1.db_conn', mock.MagicMock(return_value=...))

Given that, you will notice in your tests that db from `db = db_conn.db_name2.db_collection2' will create another mock object. Calls to that object will be recorded as well. In such a way you will be able to trace history of calls and values assignments as well.


Furthermore, see an example how to pach mongo db.

For testing of Flask apps see the documentation of flask. Also this is a nice explanation as well, and uses DB connections.

As a general hint, like @MikeMajara mentioned - separate your code more into smaller functions that are also easy to test. In tradition to TDD: write tests first, implement later, and refactor (especially DRY!)

Top answer
1 of 3
18

Since you are using pytest, I would suggest using pytest's built-in 'monkeypatch' fixture.

Consider this simple setup:

We define the function to be mocked.

"""`my_library.py` defining 'foo'."""


def foo(*args, **kwargs):
    """Some function that we're going to mock."""
    return args, kwargs

And in a separate file the class that calls the function.

"""`my_module` defining MyClass."""
from my_library import foo


class MyClass:
    """Some class used to demonstrate mocking imported functions."""
    def should_call_foo(self, *args, **kwargs):
        return foo(*args, **kwargs)

We mock the function where it is used using the 'monkeypatch' fixture

"""`test_my_module.py` testing MyClass from 'my_module.py'"""
from unittest.mock import Mock

import pytest

from my_module import MyClass


def test_mocking_foo(monkeypatch):
    """Mock 'my_module.foo' and test that it was called by the instance of
    MyClass.
    """
    my_mock = Mock()
    monkeypatch.setattr('my_module.foo', my_mock)

    MyClass().should_call_foo(1, 2, a=3, b=4)

    my_mock.assert_called_once_with(1, 2, a=3, b=4)

We could also factor out the mocking into its own fixture if you want to reuse it.

@pytest.fixture
def mocked_foo(monkeypatch):
    """Fixture that will mock 'my_module.foo' and return the mock."""
    my_mock = Mock()
    monkeypatch.setattr('my_module.foo', my_mock)
    return my_mock


def test_mocking_foo_in_fixture(mocked_foo):
    """Using the 'mocked_foo' fixture to test that 'my_module.foo' was called
    by the instance of MyClass."""
    MyClass().should_call_foo(1, 2, a=3, b=4)

    mocked_foo.assert_called_once_with(1, 2, a=3, b=4)
2 of 3
12

What you are mocking with the line emails.send_email = MagicMock() is the function

class CarsEmails:

    def send_email(self):
        ...

that you don't have. This line will thus only add a new function to your emails object. However, this function is not called from your code and the assignment will have no effect at all. Instead, you should mock the function send_email from the cars.lib.email module.

mocking the function where it is used

Once you have imported the function send_email via from cars.lib.email import send_email in your module format_email.py, it becomes available under the name format_email.send_email. Since you know the function is called there, you can mock it under its new name:

from unittest.mock import patch

from format_email import CarsEmails

@pytest.mark.parametrize("test_input,expected_output", test_data)
def test_email_payload_formatting(config, test_input, expected_output):
    emails = CarsEmails(email_client=MagicMock(), config=config)
    with patch('format_email.send_email') as mocked_send:
        emails.send_cars_email(*test_input)
        mocked_send.assert_called_with(*expected_output)

mocking the function where it is defined

Update:

It really helps to read the section Where to patch in the unittest docs (also see the comment from Martijn Pieters suggesting it):

The basic principle is that you patch where an object is looked up, which is not necessarily the same place as where it is defined.

So stick with the mocking of the function in usage places and don't start with refreshing the imports or aligning them in correct order. Even when there should be some obscure usecase when the source code of format_email would be inaccessible for some reason (like when it is a cythonized/compiled C/C++ extension module), you still have only two possible ways of doing the import, so just try out both mocking possibilities as described in Where to patch and use the one that succeeds.

Original answer:

You can also mock send_email function in its original module:

with patch('cars.lib.email.send_email') as mocked_send:
    ...

but be aware that if you have called the import of send_email in format_email.py before the patching, patching cars.lib.email won't have any effect on code in format_email since the function is already imported, so the mocked_send in the example below won't be called:

from format_email import CarsEmails

...

emails = CarsEmails(email_client=MagicMock(), config=config)
with patch('cars.lib.email.send_email') as mocked_send:
    emails.send_cars_email(*test_input)
    mocked_send.assert_called_with(*expected_output)

To fix that, you should either import format_email for the first time after the patch of cars.lib.email:

with patch('cars.lib.email.send_email') as mocked_send:
    from format_email import CarsEmails
    emails = CarsEmails(email_client=MagicMock(), config=config)
    emails.send_cars_email(*test_input)
    mocked_send.assert_called_with(*expected_output)

or reload the module e.g. with importlib.reload():

import importlib

import format_email

with patch('cars.lib.email.send_email') as mocked_send:
    importlib.reload(format_email)
    emails = format_email.CarsEmails(email_client=MagicMock(), config=config)
    emails.send_cars_email(*test_input)
    mocked_send.assert_called_with(*expected_output)

Not that pretty either way, if you ask me. I'd stick with mocking the function in the module where it is called.

🌐
DataCamp
datacamp.com › tutorial › pytest-mock
pytest-mock Tutorial: A Beginner’s Guide to Mocking in Python | DataCamp
December 18, 2024 - Once you're comfortable with basic mocking, pytest-mock offers advanced capabilities to handle more complex scenarios. Mocks can simulate more than just return values—they can also replicate behavior such as raising exceptions or dynamically changing return values. This is achieved by adding “side effects” to mocks: import pytest # production code def process_payment(payment_gateway, amount): response = payment_gateway.charge(amount) if response == "Success": return "Payment processed successfully" else: raise ValueError("Payment failed") # test code def test_process_payment_with_side_ef
🌐
Medium
medium.com › @zalun › mocking-the-unmockable-1bf3cc31dad6
Mocking the unmockable. Mocking is often challenging. Here is a… | by Piotr Zalewa | Medium
August 16, 2024 - We’re seeing the right functions called with the right values on importing the actions module. ➜ mocking_problem > poetry run pytest ============================ test session starts ============================ platform darwin -- Python 3.11.2, pytest-7.2.2, pluggy-1.0.0 rootdir: /Users/zalun/Projects/Medium/mocking_problem, configfile: pytest.ini plugins: dotenv-0.5.2 collected 6 items tests/test_action.py ...
🌐
Medium
jackskylord.medium.com › a-beginners-guide-to-getting-started-with-mocking-in-pytest-58d18b39a605
A Beginner’s Guide to Getting Started with Mocking in Pytest | by Jack P | Medium
April 10, 2024 - Our strategy for this test is to patch the requests.get method and have it return a mock object that has a set return value to the JSON method call. Here is an example of what our test will look like: # test_main.py import pytest from pytest_mock import MockerFixture from main import get_data def test_get_data(mocker: MockerFixture): fake_url = "https://fakeurl.com" mock_response = mocker.Mock() mock_response.json.return_value = {"key": "value"} mock_requests_get = mocker.patch( "main.requests.get", return_value=mock_response, ) result = get_data(url=fake_url) assert result == {"key": "value"} mock_requests_get.assert_called_once_with(fake_url)
🌐
pytest
docs.pytest.org › en › 7.1.x › how-to › monkeypatch.html
How to monkeypatch/mock modules and environments — pytest documentation
Sometimes tests need to invoke functionality which depends on global settings or which invokes code which cannot be easily tested such as network access. The monkeypatch fixture helps you to safely set/delete an attribute, dictionary item or environment variable, or to modify sys.path for importing. The monkeypatch fixture provides these helper methods for safely patching and mocking functionality in tests: