Django+pytest中只读数据库镜像未同步FactoryBoy创建的数据问题
问题分析与解决方案
核心问题原因
Django的TEST.MIRROR配置是让测试环境下只读数据库复用默认数据库的连接,但你遇到的同步问题通常由以下几个原因导致:
- 配置时机太晚:如果在测试fixture中才修改
settings.DATABASES,此时Django已经初始化了数据库连接,配置变更不会生效。 - 事务隔离机制:pytest-django默认以事务方式运行测试,FactoryBoy创建的数据处于未提交的事务中,若只读库的连接未共享该事务上下文,就无法读取到数据。
- FactoryBoy未明确指定数据库:FactoryBoy默认使用
default数据库,但如果存在自定义路由或配置,可能导致数据未写入目标库。
具体解决步骤
1. 确保配置在Django初始化前生效
将只读库的测试配置放在pytest_configure钩子中,确保在Django启动前修改settings:
# conftest.py def pytest_configure(): from django.conf import settings # 为只读库设置测试镜像 settings.DATABASES["read_only"]["TEST"] = {"MIRROR": "default"}
2. 强制FactoryBoy使用默认数据库
在Factory类中明确指定使用default数据库,避免路由干扰:
class PaymentFactory(factory.django.DjangoModelFactory): class Meta: model = Payment database = "default" # 强制指定数据库
3. 刷新只读数据库连接
如果修改配置后连接未刷新,可以在fixture中手动关闭并重建连接:
@pytest.fixture() def populate_cache() -> Callable[[CountryFactory], Household]: def _populate_cache(goodcountry: CountryFactory) -> Household: household, individuals = create_household({"business_area": afghanistan}) PaymentFactory.create_batch(5, household=household) PaymentRecordFactory.create_batch(3, household=household) # 关闭只读库连接,强制重新建立(应用MIRROR配置) from django.db import connections connections["read_only"].close() # 重新计数 payment_count_default = Payment.objects.using("default").filter(household=household).count() payment_count_read_only = Payment.objects.using("read_only").filter(household=household).count() assert payment_count_read_only == payment_count_default, "默认库与只读库的Payment数量不匹配" return household return _populate_cache
4. 检查事务配置(可选)
如果上述方法无效,可以尝试禁用事务测试(不推荐,会降低测试速度),改用django_db fixture的transaction=False参数:
@pytest.mark.django_db(transaction=False) def test_your_function(populate_cache): # 测试逻辑
内容的提问来源于stack exchange,提问作者iMitwe
相关产品推荐
相关产品推荐

