The Python 3 (>= 3.3) standard library has a great tutorial about Mock in the official documentation. For Python 2, you can use the backported library: Mock on PyPi.

Here is a sample usage. Say you want to mock the call to os.system in this function:

import os


def my_function(src_dir):
    os.system('ls ' + src_dir)

To do that, you can use the unittest.mock.patch decorator, like this:

import unittest.mock


@unittest.mock.patch('os.system')
def test_my_function(os_system):
    # type: (unittest.mock.Mock) -> None
    my_function("/path/to/dir")
    os_system.assert_called_once_with('ls /path/to/dir')

This test function will patch the os.system call during its execution. os.system is restored at the end.

Then, there are several "assert" method to check the calls, the parameters, and the results. You can also check that an exception is raised in certain circonstances.

Answer from Laurent LAPORTE on Stack Overflow
Top answer
1 of 2
9

The Python 3 (>= 3.3) standard library has a great tutorial about Mock in the official documentation. For Python 2, you can use the backported library: Mock on PyPi.

Here is a sample usage. Say you want to mock the call to os.system in this function:

import os


def my_function(src_dir):
    os.system('ls ' + src_dir)

To do that, you can use the unittest.mock.patch decorator, like this:

import unittest.mock


@unittest.mock.patch('os.system')
def test_my_function(os_system):
    # type: (unittest.mock.Mock) -> None
    my_function("/path/to/dir")
    os_system.assert_called_once_with('ls /path/to/dir')

This test function will patch the os.system call during its execution. os.system is restored at the end.

Then, there are several "assert" method to check the calls, the parameters, and the results. You can also check that an exception is raised in certain circonstances.

2 of 2
3

Just want to add an important detail.

If your code uses import system for example like this:

myls.py:

import os


def do_ls():
    os.system('ls')

Then the patch in your test should look like this:

test_myls.py:

from unittest.mock import patch


@patch('os.system')
def test_do_ls(mock_system):
    do_ls()
    mock_system.assert_called()

However, if the code uses from os import system, e.g. like this:

myls.py:

from os import system


def do_ls():
    system('ls')

Then the patch in your test should look like this:

test_myls.py:

from unittest.mock import patch


@patch('myls.system')
def test_do_ls(mock_system):
    do_ls()
    mock_system.assert_called()

This eluded me for a bit because I had forgotten to read the section on where to patch as I originally intended. If patching does not seem to work, this is one of the points to look at.

🌐
PyPI
pypi.org › project › pytest-mock
pytest-mock · PyPI
pytest mock · Development Status · 5 - Production/Stable · Framework · Pytest · Intended Audience · Developers · License · OSI Approved :: MIT License · Operating System · OS Independent · Programming Language · Python :: 3 · Python :: 3 :: Only ·
🌐
Readthedocs
pytest-mock.readthedocs.io › en › latest › index.html
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_call...
🌐
Pytest with Eric
pytest-with-eric.com › mocking › pytest-mocking
How To Mock In Pytest? (A Comprehensive Guide) | Pytest with Eric
March 23, 2026 - Let’s take a look at a basic example of mocking defined in the pytest-mock documentation. This code snippet defined a UnixFS class that contains one static method, removing a file from the disk. We can test this functionality without actually deleting a file from the disk, using the mocker.patch method to simulate the os.remove functionality.
🌐
Readthedocs
pytest-mock.readthedocs.io › en › stable
pytest-mock documentation - Read the Docs
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_call...
🌐
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.
🌐
Readthedocs
pytest-mock.readthedocs.io › en › latest › usage.html
Usage - pytest-mock documentation
pytest-mock documentation · Contents: Usage · Configuration · Remarks · Contributing · About · Changelog · Back to top · View this page · The mocker fixture has the same API as mock.patch, supporting the same arguments: import os def test_foo(mocker): # all valid calls mocker.patch('os.remove') mocker.patch.object(os, 'listdir', autospec=True) mocked_isfile = mocker.patch('os.path.isfile') The supported methods are: mocker.patch ·
🌐
Python
docs.python.org › 3 › library › unittest.mock.html
unittest.mock — mock object library
Changed in version 3.8: Added support for os.PathLike.__fspath__(). Changed in version 3.8: Added support for __aenter__, __aexit__, __aiter__ and __anext__. The following methods exist but are not supported as they are either in use by mock, can’t be set dynamically, or can cause problems:
Find elsewhere
🌐
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
pytest.skip( "this test needs assertion rewrite to work but current option " 'is "{}"'.format(option) ) · · class UnixFS: """ Wrapper to os functions to simulate a Unix file system, used for testing · the mock fixture.
Author: pytest-dev
🌐
pytest
docs.pytest.org › en › stable › how-to › monkeypatch.html
How to monkeypatch/mock modules and environments - pytest documentation
# contents of our test file e.g. test_code.py import pytest def test_upper_to_lower(monkeypatch): """Set the USER env var to assert the behavior.""" monkeypatch.setenv("USER", "TestingUser") assert get_os_user_lower() == "testinguser" def test_raise_exception(monkeypatch): """Remove the USER env var and assert OSError is raised.""" monkeypatch.delenv("USER", raising=False) with pytest.raises(OSError): _ = get_os_user_lower() This behavior can be moved into fixture structures and shared across tests: # contents of our test file e.g. test_code.py import pytest @pytest.fixture def mock_env_user(m
Top answer
1 of 3
7

If you target multiple OSs, you most probably have to test your program on each of them. These tests should typically include running your test suite on the desired OS. So the straightforward solution for unit testing the above method is to adapt the expected result on platform.system() exactly the same way you showed above:

def testUpdateString():
    var expectedResult=""
    if platform.system() == 'Darwin':
        expectedResult="http://download.com/to/OSX/version"
    elif platform.system() == 'Linux':
        expectedResult="http://download.com/to/Linux/version"
    elif platform.system() == 'Windows':
        expectedResult="http://download.com/to/Windows/version"
    else: 
        expectedResult="Seek advice on how to update."
    assertEqual(expectedResult,updateString())

Of course, the drawback is that you cannot get a full test coverage of your code when you run the tests on just one OS. In this example, this is probably acceptable, but if the "real" methods you want to test are more complicated, it may become more practicle to unit test the different parts without actually changing the OS. If that's the case, refactor the core part into a separate method which gets platform.system() as a parameter:

def updateStringPerSystem(opSys):
    if opSys == 'Darwin':
        return "http://download.com/to/OSX/version"
    elif opSys == 'Linux':
        return "http://download.com/to/Linux/version"
    elif opSys == 'Windows':
        return "http://download.com/to/Windows/version"
    else: 
        return "Seek advice on how to update."

def updateString():
     return updateStringPerSystem(platform.system())

Now you can write unit tests for updateStringPerSystem, passing all os strings you like for different tests, allowing to test the different branches for OS1, OS2, OS3, etc. even when you are running your test suite only under OS1.

Note that this works only for basic unit tests. As soon as you want to test a function which actually uses the return value for updateString in a OS dependent way, you cannot expect to test Windows functionality when running your suite under Linux, or vice versa.

2 of 3
10

Using the mock framework, you can patch platform.system().

from unittest.mock import patch

…

def testUpdateStringWithDarwin():
    with patch('platform.system', MagicMock(return_value="Darwin")):
        result = updateString()

        assert result == "http://download.com/to/OSX/version", "should be Darwin!"
🌐
Toptal
toptal.com › python › an-introduction-to-mocking-in-python
Python Mocking: A Guide to Better Unit Tests | Toptal®
May 19, 2026 - Additionally, we have no way of testing whether our rm method properly passes the argument down to the os.remove call. We can assume that it does based on the test above, but much is left to be desired. ... from mymodule import rm from unittest import mock import unittest class RmTestCase(unittest.TestCase): @mock.patch('mymodule.os') def test_rm(self, mock_os): rm("any path") # test that rm called os.remove with the right parameters mock_os.remove.assert_called_with("any path")
🌐
Adam Johnson
adamj.eu › tech › 2020 › 10 › 13 › how-to-mock-environment-variables-with-pytest
How to Mock Environment Variables in pytest - Adam Johnson
October 13, 2020 - You can apply this to all tests in a module by creating a local auto-used pytest fixture that uses mock.patch.dict: import os from unittest import mock import pytest @pytest.fixture(autouse=True) def mock_settings_env_vars(): with mock.patch.dict(os.environ, {"FROBNICATION_COLOUR": "ROUGE"}): yield def test_frobnication_colour(): assert os.environ["FROBNICATION_COLOUR"] == "ROUGE" def test_frobnication_shade(): assert os.environ["FROBNICATION_COLOUR"] == "ROUGE"
🌐
GitHub
github.com › pytest-dev › pytest-mock › issues › 84
Python3 + pytest + pytest-mock: Mocks leaking into other test functions breaking assertions? · Issue #84 · pytest-dev/pytest-mock
April 29, 2017 - #!/usr/bin/env python # -*- coding: utf-8 -*- """ test_subprocess ---------------------------------- """ import os import sys import pytest import scarlett_os # import signal # import builtins # import re class TestScarlettSubprocess(object): '''Units tests for Scarlett Subprocess, subclass of GObject.Gobject.''' def test_check_pid_os_error(self, mocker): # Feels like mocks are leaking into other tests, # stop mock before starting each test function mocker.stopall() # Setup mock objects kill_mock = mocker.MagicMock(name=__name__ + "_kill_mock_OSError") kill_mock.side_effect = OSError # patch t
🌐
PyPI
pypi.org › project › pytest-mock › 0.1.0
Client Challenge
JavaScript is disabled in your browser · Please enable JavaScript to proceed · A required part of this site couldn’t load. This may be due to a browser extension, network issues, or browser settings. Please check your connection, disable any ad blockers, or try using a different browser
🌐
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 - # mocking_problem/lib.py import json import os def get_data(): if os.environ.get("CACHED_DATA"): return json.loads(os.environ["CACHED_DATA"]) raise NotImplementedError() # tests/test_lib.py from unittest import mock import pytest from mocking_problem.lib import get_data def test_get_data_raises(): with pytest.raises(NotImplementedError): get_data() @mock.patch("mocking_problem.lib.os") def test_get_data_from_environment(mock_os): mock_os.environ = {"CACHED_DATA": '{"cached": "data"}'} assert get_data() == {"cached": "data"} The action module depends on the lib.