繁体   English   中英

Django 测试夹具拆解中的 IntegrityError

[英]Django test IntegrityError in fixture teardown

我开始使用factory_boy package 所以我设置了一些工厂并想测试创建的对象不会引发任何验证错误。

这是我正在使用的 mixin,它基本上从模块中获取每个工厂,创建一个实例,然后测试.full_clean()没有错误。 加载的用户设备是 10 个实例,ID 为 1 到 10。

class FactoriesTestCaseMixin:
    fixtures = [
        'user/tests/fixtures/user.json',
    ]
    module = None

    def test_factories(self):
        err_msg = '{name} caused errors:\n{errors}'
        factories = [
            (name, obj) for name, obj in inspect.getmembers(self.module, inspect.isclass)
            if obj.__module__ == self.module.__name__
            and not obj._meta.abstract
        ]
        for factory in factories:
            name = factory[0]
            instance = factory[1]()

            errors = None
            try:
                instance.full_clean()
            except ValidationError as e:
                errors = e

            self.assertTrue(errors is None, err_msg.format(name=name, errors=errors))

mixin 会像这样使用

from django.test import TestCase
from order import factories

class OrderFactoriesTestCase(FactoriesTestCaseMixin, TestCase):
    module = factories

但是在测试成功通过夹具拆卸后,我不断收到一个IntegrityError (下面的回溯),我不知道如何解决它,所以我的测试没有错误地通过。

如果我为每个单独的应用程序运行测试,则没有错误。 我从来没有在我的任何其他模型的夹具中遇到问题,这些夹具也有一个created_by字段。

django.db.utils.IntegrityError: insert or update on table "product_product" violates foreign key constraint "product_product_created_by_id_96713f93_fk_user_user_id"
DETAIL:  Key (created_by_id)=(13) is not present in table "user_user".

我认为正在发生的事情是先前的测试正在创建一个新用户,而工厂男孩Iterator正在选择一个新的用户 ID .. 仍然不确定为什么在成功通过测试后会导致错误。

created_by = factory.Iterator(User.objects.all())

导致此问题的模块始终具有ProductFactorySubFactory

product = factory.SubFactory(ProductFactory)

关于如何解决这个问题的任何建议?

Traceback (most recent call last):
  File "/home/Development/project/venv/lib/python3.7/site-packages/django/test/testcases.py", line 274, in __call__
    self._post_teardown()
  File "/home/Development/project/venv/lib/python3.7/site-packages/django/test/testcases.py", line 1009, in _post_teardown
    self._fixture_teardown()
  File "/home/Development/project/venv/lib/python3.7/site-packages/django/test/testcases.py", line 1177, in _fixture_teardown
    connections[db_name].check_constraints()
  File "/home/Development/project/venv/lib/python3.7/site-packages/django/db/backends/postgresql/base.py", line 246, in check_constraints
    self.cursor().execute('SET CONSTRAINTS ALL IMMEDIATE')
  File "/home/Development/project/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/home/Development/project/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 76, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/Development/project/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/Development/project/venv/lib/python3.7/site-packages/django/db/utils.py", line 89, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/Development/project/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
django.db.utils.IntegrityError: insert or update on table "product_product" violates foreign key constraint "product_product_created_by_id_96713f93_fk_user_user_id"
DETAIL:  Key (created_by_id)=(12) is not present in table "user_user".

我有一个相关的问题,我通过在我的测试用例类中专门化_fixture_teardown来解决这个问题。

_fixture_teardowndjango.test.testcases中实现以调用 django 命令“flush”,该命令试图从数据库中删除所有数据。 我不知道这对你是否有用。 在我保留测试数据库并使用--keepdb ,它导致了问题。

由于我不需要(或不想)刷新测试数据库,我只是专门使用该方法什么都不做。 这解决了我的问题,可能有助于解决你的问题。

我在非常相似的情况下找到了问题的原因。 我正在使用 model_bakery 创建 model。 我的 ModelAdmin 中有这个方法:

def formfield_for_foreignkey(self, db_field, request, **kwargs):
    if db_field.name == "author":
        db_field.default = request.user
        return super(PostAdmin, self).formfield_for_foreignkey(
            db_field, request, **kwargs
        )

首先执行渲染 ModelAdmin 列表视图的测试,该视图调用此 function 并将默认request.user设置为Post.author字段。

在下一个测试中(在request.user已经从数据库中删除之后)我创建了新的 Post :

baker.make("Post", title="Foo post")

它将不存在的默认用户的 ID 分配给author字段。

然后它在_fixture_teardown或只是简单的print(post.author)期间引发异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM