使用@pytest.mark.django_db时如何避免pytest自动将测试包裹在事务中
pytest-django测试transaction.on_commit()不触发的解决方案
方案1:手动执行on_commit回调(优先推荐)
不需要修改默认事务回滚逻辑,测试速度无损失,直接调用Django内置的回调捕获工具即可:
- 导入
django.test.TestCase,使用captureOnCommitCallbacks上下文管理器,将execute参数设为True,上下文退出时会自动执行所有注册的on_commit回调
示例代码:
import pytest from django.test import TestCase from your_app.module import your_function_with_on_commit @pytest.mark.django_db def test_on_commit_logic(): with TestCase.captureOnCommitCallbacks(using="default", execute=True): # 执行包含on_commit的业务代码 your_function_with_on_commit() # 此处on_commit逻辑已执行,可直接断言结果 # assert 你的断言逻辑
方案2:修改django_db标记开启真实事务提交
给@pytest.mark.django_db添加transaction=True参数,pytest不会再将测试包裹在自动回滚的事务中,会真实提交事务,自然触发on_commit逻辑:
示例代码:
import pytest from your_app.module import your_function_with_on_commit @pytest.mark.django_db(transaction=True) def test_on_commit_logic(): your_function_with_on_commit() # 此处on_commit逻辑已随事务提交触发 # assert 你的断言逻辑
方案3:使用transactional_db fixture
和方案2效果完全一致,直接在测试函数参数中引入transactional_db fixture即可,不需要额外修改标记:
示例代码:
import pytest from your_app.module import your_function_with_on_commit def test_on_commit_logic(transactional_db): your_function_with_on_commit() # 此处on_commit逻辑已随事务提交触发 # assert 你的断言逻辑
注意事项
- 方案2、3会真实提交事务,测试结束后pytest-django会自动执行
flush命令清理测试数据,测试速度比默认模式慢,适合无法用方案1覆盖的场景 - 如果你的
on_commit逻辑依赖其他数据库事务特性,优先选择方案2、3
内容的提问来源于stack exchange,提问作者Yituo
相关产品推荐
相关产品推荐

