Mock Python version with unittest.mock.patch

Use unittest.mock.patch to simulate a specific Python version and test version-dependent behavior.

Medium Python 3.8+ Aug 9, 2026 Modern tooling 13 views 0 copies

Python code

16 lines
Python 3.8+
import sys
import unittest
from unittest.mock import patch

class TestPythonVersion(unittest.TestCase):
    @patch("sys.version_info", (3, 9, 0, "final", 0))
    def test_python_version_pinned(self):
        self.assertEqual(sys.version_info[:2], (3, 9))
        print(f"Pinned version: {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")

    def test_real_python_version(self):
        print(f"Actual version: {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")
        self.assertTrue(sys.version_info >= (3, 9))

if __name__ == "__main__":
    unittest.main()

Output

stdout
Pinned version: 3.9.0
.
Actual version: 3.10.12 (example)
.

----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK

How it works

The @patch("sys.version_info", (3, 9, 0, "final", 0)) decorator temporarily replaces sys.version_info with a fake tuple, letting you test code that branches on Python version. Since patch applies only to the decorated test method, other tests still see the real interpreter version. This is great for testing compatibility layers, conditional imports, or deprecated API warnings. To simulate different versions, just pass a different tuple—like (3, 11, 4, "final", 0).

Common mistakes

  • Patching the wrong path—must match where the object is used, not where it's defined.
  • Forgetting that `patch` as a decorator only affects the decorated test method.
  • Assuming `sys.version_info` is a simple tuple when it's actually a `sys.version_info` object; a tuple works fine for equality but may break attribute access beyond the first two elements.

Variations

  1. Use `with patch("sys.version_info", (3, 8, 0, "final", 0)):` statement for conditional patching.
  2. Use `unittest.mock.mock_version` to simulate version in third-party libraries.

Real-world use cases

  • Testing compatibility of your library against multiple Python versions in CI without separate jobs.
  • Verifying that code paths handling deprecated features behave correctly on older interpreters.
  • Ensuring feature flags or version-dependent imports activate the right module during testing.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Modern tooling

Related tutorials and quizzes for this topic.