应使用 unittest.mock.patch.dict 临时替换 os.environ 以避免全局污染,或优先选用 pytest 的 monkeypatch fixture 实现自动清理和细粒度控制。

用 unittest.mock.patch 临时替换 os.environ
直接改 os.environ 是全局污染,测试之间会互相干扰。必须用 patch 在测试生命周期内隔离修改。
最稳妥的方式是 patch os.environ 本身(注意不是 patch os.getenv):
import os
from unittest.mock import patch
<p>def test_with_custom_env():
with patch.dict(os.environ, {"API_URL": "<a href="https://www.php.cn/link/ec65ca05e999a40eaaa22d6ec8432e4c">https://www.php.cn/link/ec65ca05e999a40eaaa22d6ec8432e4c</a>", "DEBUG": "1"}):
assert os.getenv("API_URL") == "<a href="https://www.php.cn/link/ec65ca05e999a40eaaa22d6ec8432e4c">https://www.php.cn/link/ec65ca05e999a40eaaa22d6ec8432e4c</a>"
assert os.getenv("DEBUG") == "1"</p><h1>出了 with 块,env 恢复原状</h1><p></p>
- 用
patch.dict()而不是patch.object(),因为os.environ是os._Environ实例,行为接近 dict - 传入的字典会 deep-copy 后合并进当前
os.environ,不影响原始值 - 如果想清空所有环境变量再设新值,加参数
clear=True
Pytest 用户优先用 monkeypatch fixture
pytest 内置的 monkeypatch 更轻量、自动清理,且支持更细粒度控制(比如只 patch 单个 key)。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
def test_with_monkeypatch(monkeypatch):
monkeypatch.setenv("DB_NAME", "testdb")
monkeypatch.delenv("CACHE_ENABLED", raising=False)
assert os.getenv("DB_NAME") == "testdb"
assert os.getenv("CACHE_ENABLED") is None
-
setenv(key, value):设置或覆盖单个变量 -
delenv(key, raising=True):删除变量;raising=False表示 key 不存在也不报错 - fixture 自动在测试结束时还原,无需手动管理生命周期
避免在 setUp / setup_method 里硬编码环境变量
这类写法看似省事,实则埋下隐患:变量残留、难以组合多个测试场景、与 CI 环境冲突。
- 不要在
setUp中执行os.environ["FOO"] = "bar"—— 这是永久修改,后续测试可能读到错误值 - 不要依赖测试前手动
export FOO=bar启动 pytest —— 本地开发和 CI 行为不一致 - 如果多个测试共用同一组 env,抽成 fixture 或参数化测试,而不是复用
setUp
Mock 失败的典型现象和排查点
常见表现:测试里 os.getenv("X") 还是返回 None 或旧值,mock 像没生效。
- patch 目标错了:比如 patch 了
my_module.os.getenv,但代码实际调用的是os.getenv(即从os模块顶层导入)—— 必须 patch **被使用处** 的路径 - patch 位置不对:在函数外 patch
os.environ,但测试函数内部又重新 import 了os—— patch 必须在目标作用域生效期间存在 - 用了
patch("os.getenv")却忘了return_value,而代码里又用了os.environ.get()—— 不同访问方式需分别 mock
真正动态的环境变量 mock,核心就两条:隔离作用域 + 精确 patch 位置。其余都是围绕这两点做适配。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










