How to Mock subprocess.run returncode in Python

Simulate subprocess.run return codes in tests with unittest.mock.patch and CompletedProcess.

Easy Python 3.9+ Aug 9, 2026 Testing & modern typing 14 views 0 copies

Python code

18 lines
Python 3.9+
import subprocess
from unittest.mock import patch


def run_command(cmd):
    result = subprocess.run(cmd, capture_output=True, text=True)
    return result.returncode


if __name__ == "__main__":
    with patch("subprocess.run") as mock_run:
        # Simulate a successful command (returncode 0)
        mock_run.return_value = subprocess.CompletedProcess(args=["ls"], returncode=0)
        print(f"Success case returncode: {run_command(['ls'])}")

        # Simulate a failed command (returncode 1)
        mock_run.return_value = subprocess.CompletedProcess(args=["false"], returncode=1)
        print(f"Failure case returncode: {run_command(['false'])}")

Output

stdout
Success case returncode: 0
Failure case returncode: 1

How it works

patch('subprocess.run') replaces the real subprocess.run with a MagicMock, so calls are captured and you control the return value. subprocess.CompletedProcess is a built-in dataclass with attributes like args and returncode, making it perfect for realistic mocks. Setting mock_run.return_value to a CompletedProcess with the desired returncode simulates success or failure without executing any actual command. This keeps tests fast, deterministic, and avoids side effects on the real system.

Common mistakes

  • Mocking subprocess.run but forgetting to set return_value, which defaults to a MagicMock and can cause AttributeErrors.
  • Using subprocess.CompletedProcess without required arguments like `args`.
  • Patching `subprocess.Popen` when the code uses `subprocess.run` internally — patch what the code actually calls.

Variations

  1. Use `unittest.mock.patch.object(subprocess, 'run')` to patch more explicitly.
  2. Use a side_effect with a list of CompletedProcess objects to simulate different returncodes in sequence.

Real-world use cases

  • Unit-testing scripts that branch on the exit code of system commands like `git` or `pip`.
  • Verifying that automation retries failed commands by simulating non-zero returncodes without shelling out.
  • Testing CLI wrapper functions that should log or raise when a subprocess fails.

Sponsored

Run this sample

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

Open editor

More from Testing & modern typing

Related tutorials and quizzes for this topic.