【问题标题】:How to reproduce the following IntegrityError in django unit test?如何在 django 单元测试中重现以下 IntegrityError?
【发布时间】:2019-04-06 05:44:39
【问题描述】:

我有两个模型“问题”和“字体”。在这些“问题”中是不可删除的模型。并且 Question 有对 Font 的引用。

因此,如果删除字体,则相关字体的引用将设置为无,如果删除问题,则由于问题是不可删除的模型,因此不会从数据库中删除其活动字段将设置为错误,因此无法通过 Django 的“对象”模型管理器进行查询。在这种情况下,如果我删除了一个问题,然后,如果我尝试删除字体,它会抛出“IntegrityError”,因为软删除的问题仍然引用该字体。

问题是我无法在单元测试中重现这一点。在单元测试中,字体被优雅地删除。 在前端,我得到以下信息。

update or delete on table "custom_fonts_customfont" violates foreign key constraint "font_id_refs_id_794a5361" on table "questions_question"
DETAIL:  Key (id)=(1026) is still referenced from table "questions_question".

我尝试使用 Django 的 Transaction 测试用例,我还确保该问题在测试用例中被软删除,并使用 Django 的“未过滤”模型管理器确认问题对字体的引用。

class Question(ExtendedOrderedModel, NonDeletableModel):
      font = models.ForeignKey('custom_fonts.CustomFont', null=True, on_delete=models.SET_NULL)

这是我的测试用例

    def test_font_deletion_after_question_deletion_(self):
        self.question.font = CustomFont.objects.create(
            name='roboto', font_type='truetype', path='font.ttf', created_by=self.owner
        )
        self.question.save()
        self.question.delete()

        CustomFont.objects.all().delete() # This should raise an error but it is not raising

        print(Question.objects.all()) # []
        print(Question.unfiltered.first().font_id) # 1

【问题讨论】:

    标签: python django


    【解决方案1】:

    终于找到了原因。这是因为

    在 Postgresql 中,约束设置为 DEFERRABLE INITIALLY DEFERRED。这个 导致它仅在事务执行时检查这些约束 坚定的。 (这也可能会影响 Oracle 后端,基于快速 搜索。)这会导致 TestCase 出现问题:因为它们永远不会 已提交,许多约束违反永远不会被触发。

    在我的测试用例中添加以下行对我有帮助。

    cursor = connection.cursor()
    cursor.execute('SET CONSTRAINTS ALL IMMEDIATE')
    

    来源:https://code.djangoproject.com/ticket/11665

    【讨论】:

      猜你喜欢
      • 2022-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 2017-12-01
      • 2013-05-08
      相关资源
      最近更新 更多