Mocking subprocess and HTTP in Python
Half of an automation script is calls you cannot make in a test - a subprocess, an API, a host that may be down. monkeypatch and unittest.mock.patch replace them, and both have one rule that catches everybody: you patch the name where it is looked up, not where it is defined. This guide gets that wrong on purpose and measures the difference, then shows the mock that passes a test with a typo in it.
Remote Hosts and CI/CD Guide 36 of 39 Advanced
- Control nodeUbuntu 26.04 LTS
- Python3.14.4
- requests2.34.2
- paramiko5.0.0
- TimeAbout 22 min
unittest.mock is standard library. call_args.args and call_args.kwargs need Python 3.8; before that it was tuple indexing. Mock(spec=...) and autospec=True are the two things that make a mock refuse a typo.
- pytest9.1.1
- PyYAML6.0.3
- boto3 / botocore1.43.78
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| RUNNER01 | 192.168.0.27 | Ubuntu 26.04 LTS | Control node - every script in this path runs here | 2 Core | 4 GB | 50 GB |
This guide includes
Use this because half of an automation script is calls you cannot make in a test. This matters because a Mock answers anything you ask it - so the mock that lies passes a test the real code would fail.
- patching the environment with monkeypatch
- faking
subprocess.runwith a real CompletedProcess - meeting the patch target that looks right and is not
- faking an HTTP call, and seeing the mock that lies
- writing a fake that is not a mock, and the test that needs no mock at all
Before you start
- guide 35 - the runner and the assertions.
- guide 17 - the call being faked.
- guide 24 - and the other one.
-
The code that touches the outside world
-
monkeypatch, for the environment
-
A fake subprocess.run
-
The target that looks right and is not
-
A fake HTTP call
-
The mock that lies
-
A fake that is not a mock at all
-
And the test that needs no mock at all