首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >测试包含在提交db事务后发生的函数调用的django `post_save`信号

测试包含在提交db事务后发生的函数调用的django `post_save`信号
EN

Stack Overflow用户
提问于 2022-06-07 08:59:53
回答 1查看 387关注 0票数 0

在运行django测试时,不提交数据库事务。如何测试对象创建触发的事件,但这发生在提交db事务之后?

我有一个Campaign模型和下面的post_save信号。使用Django TestCase很难断言在创建新的transaction.on_commit对象时调用了transaction.on_commit中的函数。当信号在测试上下文中运行时,它总是认为正在编辑现有的活动对象,而不是新创建的对象。因此,我不能测试if语句的else分支。

如果Campaign.objects.filter(pk=instance.pk).exists()是假的,我如何测试这个案例?

信号:

代码语言:javascript
复制
@receiver(post_save, sender=Campaign, dispatch_uid="apps.writing.signals.create_handwriting")
def create_handwriting(sender, instance, **kwargs):
    """Whenever a campaign is created or updated, trigger the handwriting cloud function to (re)generate the
    handwriting image.
    """

    if Campaign.objects.filter(pk=instance.pk).exists():
        transaction.on_commit(
            lambda: log_campaign_progress(pk=instance.pk, status="t2h-edited", stage="campaign")
        )
        transaction.on_commit(lambda: delete_campaign_pages(campaign_pk=instance.pk))
    else:
        transaction.on_commit(
            lambda: log_campaign_progress(pk=instance.pk, status="t2h-created", stage="campaign")
        )

    transaction.on_commit(lambda: enqueue_handwriting_generation(campaign_pk=instance.pk))

测试:

代码语言:javascript
复制
class TestSignals(TestCase):
    def setUp(self):
        self.factory = RequestFactory()

    @mock.patch("lettergun.apps.writing.signals.log_campaign_progress")
    @mock.patch("lettergun.apps.writing.signals.enqueue_handwriting_generation")
    @mock.patch("lettergun.apps.writing.signals.delete_campaign_pages")
    def test_create_handwriting_edit_existing_campaign(
        self, delete_campaign_pages, enqueue_handwriting_generation, log_campaign_progress
    ):
        # disconnected in the factory so we need to reconnect it here
        signals.post_save.connect(
            sender=Campaign,
            dispatch_uid="apps.writing.signals.create_handwriting",
            receiver=create_handwriting,
        )
        enqueue_handwriting_generation.return_value = True
        log_campaign_progress.return_value = True

        with self.captureOnCommitCallbacks(execute=True) as callbacks:
            user = G(User)
            campaign = G(Campaign, user=user)

        assert Campaign.objects.get(pk=campaign.pk)
        assert Campaign.objects.filter(pk=campaign.pk).exists()

        enqueue_handwriting_generation.assert_called_with(campaign_pk=campaign.pk)
        log_campaign_progress.assert_called_with(pk=campaign.pk, stage="campaign", status="t2h-edited")
        delete_campaign_pages.assert_called_with(campaign_pk=campaign.pk)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-30 10:36:58

django.test.TestCase不支持事务(提交数据库事务并在测试后进行清理会导致性能损失)。根据https://docs.djangoproject.com/en/4.0/topics/testing/tools/#django.test.TestCase

  • 将测试封装在两个嵌套的原子()块中:一个用于整个类,另一个用于每个测试。因此,如果要测试某些特定的数据库事务行为,请使用TransactionTestCase.

您应该使用TransactionTestCase https://docs.djangoproject.com/en/4.0/topics/testing/tools/#django.test.TransactionTestCase

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72528545

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档