本文介绍了测试IntegrityError UNIQUE约束失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对电子邮件和商店有一个unique_together约束.我使用以下代码测试唯一约束.我期望使用assertRaise通过测试,但结果却相反.我在这里想念的是什么?

I have a unique_together constraint for email and store. I have used the following code to test the unique constraint. I'm expecting to pass the test with assertRaise but the result shows the opposite. What I'm missing here?

from django.db.backends.sqlite3.base import IntegrityError

class TestUserModel(TestCase):
    def setUp(self):
        self.store1 = Store.objects.create(name='store1')
        self.store2 = Store.objects.create(name='store2')

    def multiple_user_with_same_email_and_store(self):
        data1 = dict(email="[email protected]", password="a", store=self.store1)
        data2 = dict(email="[email protected]", password="abc", store=self.store1)
        self.user1 = User.objects.create(**data1)
        user2 = User(**data2)
        self.assertRaises(IntegrityError, user2.save)

追踪

    Creating test database for alias 'default'...
E
======================================================================
ERROR: multiple_user_with_same_email_and_store (user.tests.test_models.TestUserModel)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/ram/nk/project/helper/helper/user/tests/test_models.py", line 25, in multiple_user_with_same_email_and_store
    self.assertRaises(IntegrityError, user2.save)
  File "/usr/lib/python2.7/unittest/case.py", line 473, in assertRaises
    callableObj(*args, **kwargs)
  File "/home/ram/.virtual/helper/local/lib/python2.7/site-packages/django/db/models/base.py", line 734, in save
    force_update=force_update, update_fields=update_fields)
  File "/home/ram/.virtual/helper/local/lib/python2.7/site-packages/django/db/models/base.py", line 762, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "/home/ram/.virtual/helper/local/lib/python2.7/site-packages/django/db/models/base.py", line 846, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "/home/ram/.virtual/helper/local/lib/python2.7/site-packages/django/db/models/base.py", line 885, in _do_insert
    using=using, raw=raw)
  File "/home/ram/.virtual/helper/local/lib/python2.7/site-packages/django/db/models/manager.py", line 127, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/ram/.virtual/helper/local/lib/python2.7/site-packages/django/db/models/query.py", line 920, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/home/ram/.virtual/helper/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 974, in execute_sql
    cursor.execute(sql, params)
  File "/home/ram/.virtual/helper/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/home/ram/.virtual/helper/local/lib/python2.7/site-packages/django/db/utils.py", line 97, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/home/ram/.virtual/helper/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/home/ram/.virtual/helper/local/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py", line 318, in execute
    return Database.Cursor.execute(self, query, params)
IntegrityError: UNIQUE constraint failed: user_user.email, user_user.store_id


    ----------------------------------------------------------------------
    Ran 1 test in 0.003s

    FAILED (errors=1)

用户模型扩展了AbstractUser(User上没有添加其他任何东西),如下所示:

User model extends AbstractUser (nothing other added at User), which is as follow

class AbstractUser(auth_models.AbstractBaseUser, PermissionsMixin):

    email = models.EmailField(_('email address'))
    store = models.ForeignKey(Store, verbose_name=_('Store Name'), null=True)
    first_name = models.CharField(_('First name'), max_length=255, blank=True)
    last_name = models.CharField(_('Last name'), max_length=255, blank=True)
    is_staff = models.BooleanField(
            _('Staff status'), default=False,
            help_text=_('Designates whether the user can log into this admin '
                        'site.'))
    is_active = models.BooleanField(
            _('Active'), default=True,
            help_text=_('Designates whether this user should be treated as '
                        'active. Unselect this instead of deleting accounts.'))
    date_joined = models.DateTimeField(_('date joined'),
                                       default=timezone.now)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['store']

    class Meta:
        abstract = True
        verbose_name = _('User')
        verbose_name_plural = _('Users')
        unique_together = ('email', 'store')

和UserManager

and UserManager

class UserManager(auth_models.BaseUserManager):
    def create_user(self, store, email, password=None, **extra_fields):
        """
        Creates and saves a User with the given email and
        password.
        """
        now = timezone.now()
        if not email:
            raise ValueError('The given email must be set')
        email = UserManager.normalize_email(email)
        try:
            with transaction.atomic():
                store, created = Store.objects.get_or_create(name=store)
                user = self.model(email=email, store=store, is_staff=False, is_active=True, is_superuser=False,
                        last_login=now, date_joined=now, **extra_fields)
                user.set_password(password)
                user.save(using=self._db)
        except Error as e:
            logging.ERROR(e)
            raise Error("Internal Error: Unable to create user")
        return user

    def create_superuser(self, store, email, password, **extra_fields):
        u = self.create_user(store, email, password, **extra_fields)
        u.is_staff = True
        u.is_active = True
        u.is_superuser = True
        u.save(using=self._db)
        return u

    def create_staffuser(self, store, email, password, **extra_fields):
        u = self.create_user(store, email, password, **extra_fields)
        u.is_staff = True
        u.is_active = True
        u.is_superuser = False
        u.save(using=self._db)
        return u

版本:1.8

推荐答案

因此错误在右行(在 assertRaises 中)出现,但是我怀疑有两种不同的 IntegrityError 类在这里发挥作用-一种是由测试导入的,另一种是由数据库后端引发的.

So the error is being raised at the right line (in assertRaises), but I suspect there are two different kinds of IntegrityError classes at play here - one that is imported by the test, and one that is raised by the database backend.

例如: django.db.backends.postgresql.base.IntegrityError django.db.backends.sqlite3.base.IntegrityError 不同.最重要的是,有Django异常包装器 django.db.utils.IntegrityError

e.g.: django.db.backends.postgresql.base.IntegrityError is not the same as django.db.backends.sqlite3.base.IntegrityError. On top of that, there is the Django exception wrapper django.db.utils.IntegrityError

可以使用 self.assertRaises 作为上下文管理器来调试和验证问题:

The issue can be debugged and verified by using self.assertRaises as a context manager:

with self.assertRaises(Exception) as raised:  # top level exception as we want to figure out its exact type
    user2.save()
self.assertEqual(IntegrityError, type(raised.exception))  # if it fails, we'll get the correct type to import

这篇关于测试IntegrityError UNIQUE约束失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-25 04:20