4

我正在尝试为我的 django 项目运行以下单元测试:

from django.test import TestCase
from django.contrib.auth.models import User
from CarbonEmissions import models

class DbTest(TestCase):
    #is called before each test case (e.g test_insertingUserProfiles)
    def setUp(self):
        self.user = User.objects.create(username='ppoliani')
        self.userProfile = models.UserProfile.objects.create(user=self.user, title='Mr', type='student', occupation='student')

    def test_insertingUserProfiles(self):
        """
            Testing the insertion of user profiles into our datbase 
        """
        self.assertEqual(self.user.get_profile().title,'Mr')

    #is called after each test case (e.g test_insertingUserProfiles)
    def tearDown(self):
        self.user.delete()
        self.userProfile.delete()

测试失败,抛出以下错误:

IntegrityError: duplicate key value violates unique constraint "CarbonEmissions_userprofile_user_id_key" DETAIL:  Key (user_id)=(1) already exists.

我无法理解该代码有什么问题。

4

4 回答 4

2

错误消息告诉您约束“CarbonEmissions_userprofile_user_id_key”失败,因为在某些表中,已经有一行 user_id 等于 1。

要解决这个问题,使用 pgAdminIII 查看约束和数据可能是最简单的方法,它通常与 PostgreSQL 一起安装。展开表名以查看列、约束等。展开约束以查看它们的名称和属性。右键单击表名称,然后选择“查看数据”以获取可让您浏览数据的选项。

于 2012-08-11T15:10:56.713 回答
0

也许用户配置文件对象已经由一些监听用户对象的 post_save 信号的代码创建?如果是这样,那么您在 setUp 函数中创建的配置文件是重复的。

于 2012-08-11T22:01:33.973 回答
0

您还没有发布完整的堆栈跟踪(请这样做!)但我认为错误出现在创建UserProfile对象的行上。Django 文档明确指出,添加新用户时指定配置文件类AUTH_PROFILE_MODULE不会自动创建该类型的模型:

如果配置文件不存在,则 get_profile() 方法不会创建配置文件。您需要为 User 模型的 django.db.models.signals.post_save 信号注册一个处理程序,并且在处理程序中,如果 created 为 True,则创建关联的用户配置文件:

因此,正如 zifot 建议的那样,您的项目中可能还有一些其他代码创建了一个UserProfile. 如果这样做正确,只需self.userProfile = models.UserProfile.objects.create(...从中删除您的线路setUp并通过以下方式访问配置文件

self.user.get_profile()
于 2012-08-11T23:09:46.107 回答
0

这是一个老问题,但我最近遇到了类似的问题。

我有一个模型 ,Quote它有一个名为 的字段reported。我最近将此字段更改为私有,并创建了一个属性来设置和获取它。(因为它必须更新另一个模型,而且我不想通过信号或在序列化程序中执行此逻辑。)当我更改它时,我在单元测试中遇到了同样的错误。

我的模型(简化)是

class Quote(TimeStampedModel):

    _reported = models.BooleanField(
        default=False,
    )

    @property
    def reported(self):
        return self._reported

    @reported.setter
    def reported(self, value):
        self._reported = value
        if value:
            try:
                self.authorization_form.reported = True
                self.authorization_form.save()
            except AuthorizationForm.DoesNotExist:
                pass
        self.save()

我失败的单元测试是

def test_can_set_reported(self):
    quote = Quote.objects.create(
        reported=True,
    )

为了让它通过,我把它改成了

def test_can_set_reported(self):
    quote = Quote.objects.create(
        # reported=True,
    )
    quote.reported = True
    quote.save()

我怀疑问题是我在设置save()时调用了该方法reported。因此,经理创建了对象并设置了reported字段(称为保存),然后尝试保存实例。这可能都发生在单个事务中,因此引入了重复密钥。

查看堆栈跟踪是值得的,我注意到两个插入语句。

这可能表明我应该将这个逻辑移到别处。(我会这样做。)但是遇到这个很有趣。

于 2017-11-30T15:55:55.960 回答