应使用@override_settings装饰器或pytest-django的settings fixture修改Django配置,避免直接修改settings对象;环境变量需用monkeypatch处理,确保测试隔离性。

测试时直接改 settings 对象会出问题
直接在测试里写 settings.DEBUG = True 或 settings.DATABASES = {...} 是危险的。Django 的 Settings 类做了缓存和只读保护,运行时修改可能被忽略,或影响后续测试(尤其是并行执行时)。更糟的是,某些配置(如 INSTALLED_APPS)在 Django 启动后已注册信号、加载模型,中途改了也白改。
用 @override_settings 装饰器最稳妥
这是 Django 官方推荐方式,它会在测试函数/类执行前后自动备份和还原配置,且支持嵌套。注意它只对通过 django.conf.settings 访问的值生效,不改变模块级变量或已实例化的对象(比如已创建的数据库连接)。
- 单个测试函数:在函数上加
@override_settings(DEBUG=True, LANGUAGE_CODE='en') - 整个测试类:在类上加
@override_settings(CACHES={'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}}) - 临时进入上下文:用
with override_settings(EMAIL_BACKEND='django.core.mail.backends.locmem.EmailBackend'):包裹代码块
pytest-django 用户该用 settings fixture
如果你用 pytest,pytest-django 提供了 settings fixture,它是可写的、作用域可控的副本,比 @override_settings 更灵活:
def test_something(settings):
settings.DEBUG = False
settings.SECRET_KEY = 'test-key'
# 此时 settings 对象已被修改,且仅对当前测试有效
但要注意:这个 settings fixture 不会触发 Django 内部重载逻辑(比如重新初始化中间件),所以像 MIDDLEWARE 这类启动期配置仍需用 @override_settings 配合 django.test.TestCase 才可靠。
立即学习“Python免费学习笔记(深入)”;
需要改环境变量?用 os.environ + monkeypatch
很多项目从 os.environ 读取配置(如 os.environ.get('DB_URL')),这时不能靠 @override_settings。推荐 pytest 的 monkeypatch fixture:
-
monkeypatch.setenv('DEBUG', '1')—— 设置环境变量 -
monkeypatch.delenv('CACHE_URL', raising=False)—— 删除环境变量 - 务必在测试函数参数中声明
monkeypatch,pytest 会自动注入
别手动改 os.environ 后忘了恢复,否则污染全局状态。
改配置本身不难,难的是分清「改给谁看」:是改给 Django 的 settings 模块、还是改给你的业务代码读的环境变量、还是改给某个已初始化的第三方客户端。混用手段会导致行为不一致,尤其在 CI 环境里表现诡异。


















