在Django Factory Boy中,是否可以静音特定的接收器(不是所有信号)?

jutyujz0  于 2023-01-18  发布在  Go
关注(0)|答案(2)|浏览(117)

在Django项目中,我们有一个接收器函数,用于接收User模型发送的post_save信号:

@receiver(post_save, sender=User)
def update_intercom_attributes(sender, instance, **kwargs):
    # if the user is not yet in the app, do not attempt to setup/update their Intercom profile.
    if instance.using_app:
        intercom.update_intercom_attributes(instance)

这个接收器调用一个外部API,我们希望在用factory_boy生成测试装置时禁用它。然而,就我从https://factoryboy.readthedocs.io/en/latest/orms.html#disabling-signals中所了解到的,我们所能做的就是静音 * 所有 * post_save信号,而不是特定的接收器。
目前,我们的做法是定义一个IntercomMixin,每个测试用例都从它继承(在继承链的第一个位置):

from unittest.mock import patch

class IntercomMixin:
    @classmethod
    def setUpClass(cls):
        cls.patcher = patch('lucy_web.lib.intercom.update_intercom_attributes')
        cls.intercomMock = cls.patcher.start()
        super().setUpClass()

    @classmethod
    def tearDownClass(cls):
        super().tearDownClass()
        cls.patcher.stop()

然而,将这种mixin添加到每个测试用例中是麻烦和重复的,理想情况下,我们希望将这种修补功能构建到测试工厂本身中。
有什么方法可以在Factory Boy中做到这一点吗?(我看了源代码(https://github.com/FactoryBoy/factory_boy/blob/2d 735767 b7 f3 e1 f9 adfc 3f 14 c28 eeef 7acbf 6 e5 a/factory/django.py#L256),看起来__enter__方法正在设置signal.receivers = [];也许可以修改它,使其接受receiver函数并将其从signal.receivers列表中弹出)?

dxxyhpgq

dxxyhpgq1#

对于任何人寻找只是这件事,并发现自己对这个问题,你可以在这里找到解决方案:https://stackoverflow.com/a/26490827/1108593
基本上......在测试方法本身上调用@factory.django.mute_signals(post_save);或者在我的例子中是setUpTestData方法。
试验:

# test_models.py
from django.test import TestCase
from django.db.models.signals import post_save
from .factories import ProfileFactory
import factory

class ProfileTest(TestCase):
    @classmethod
    @factory.django.mute_signals(post_save)
    def setUpTestData(cls):
        ProfileFactory(id=1) # This won't trigger user creation.
        ...

配置文件工厂:

#factories.py
import factory
from factory.django import DjangoModelFactory
from profiles.models import Profile
from authentication.tests.factories import UserFactory

class ProfileFactory(DjangoModelFactory):
    class Meta:
        model = Profile

    user = factory.SubFactory(UserFactory)

这允许工厂按预期工作,并允许测试根据需要操作工厂以测试它们所需的内容。

nhaq1z21

nhaq1z212#

如果您想静音某个类型的所有信号,您可以直接在工厂配置。例如:

from django.db.models.signals import post_save

@factory.django.mute_signals(post_save)
class UserFactory(DjangoModelFactory):
    ...

相关问题