Django 单元测试因唯一约束而失败

时间:2021-02-17 01:48:14

标签: django unit-testing django-rest-framework django-testing django-tests

我正在编写一个测试来验证字段的唯一性。在这个测试中,我试图验证产品的 slug 是唯一的。我最初的测试如下:

from django.test import TestCase
from django.urls import reverse
from django.forms import ValidationError
from django.db.utils import IntegrityError
from rest_framework.test import APIClient
from rest_framework import status

from .factories import ProductFactory
from .models import Product
from .serializer import ProductSerializer

PRODUCTS_URL = reverse('product-list')

def create_product(**params):
    """ Helper function to create a new product """
    return Product.objects.create(**params)

class PrivateProductsTests(TestCase):

    def setUp(self):
        self.client = APIClient()
    
    
    def test_an_error_occurs_when_forcing_the_same_slug_for_different_products(self):

        product1 = ProductFactory.create(slug='')
        serializer1 = ProductSerializer(product1)
        product1_data = serializer1.data

        product1 = create_product(**product1_data)

        product2 = ProductFactory.create(slug=product1.slug)
        serializer2 = ProductSerializer(product2)
        product2_data = serializer2.data

        self.assertRaises(IntegrityError, create_product(**product2_data))

但它失败并出现以下错误:

<块引用>

django.db.utils.IntegrityError:重复键值违反唯一 约束“products_product_slug_key”细节:键 (slug)=(james-maxwell) 已经存在。

环顾四周,我发现以下问题提供了答案:

Fail on Testing IntegrityError UNIQUE constraint

现在我的测试看起来像:

def test_an_error_occurs_when_forcing_the_same_slug_for_different_products(self):

    product1 = ProductFactory.create(slug='')
    serializer1 = ProductSerializer(product1)
    product1_data = serializer1.data

    product1 = create_product(**product1_data)

    product2 = ProductFactory.create(slug=product1.slug)
    serializer2 = ProductSerializer(product2)
    product2_data = serializer2.data

    # there are two kinds of IntegrityError classes at play here, one
    # that's imported from the test and one raised by the db
    with self.assertRaises(IntegrityError) as raised:
        product2 = create_product(**product2_data)
    
    # print(type(raised.exception))
    self.assertEqual(IntegrityError, type(raised.exception))

但我想更进一步检查系统中没有存储任何内容,因此我将测试修改为(检查最后两行):

def test_an_error_occurs_when_forcing_the_same_slug_for_different_products(self):

product1 = ProductFactory.create(slug='')
serializer1 = ProductSerializer(product1)
product1_data = serializer1.data

product1 = create_product(**product1_data)

product2 = ProductFactory.create(slug=product1.slug)
serializer2 = ProductSerializer(product2)
product2_data = serializer2.data
print(product1.slug)
print(product2_data)

# self.assertRaises(IntegrityError, create_product(**product2_data))

# there are two kinds of IntegrityError classes at play here, one
# that's imported from the test and one raised by the db
with self.assertRaises(IntegrityError) as raised:
    product2 = create_product(**product2_data)

# print(type(raised.exception))
self.assertEqual(IntegrityError, type(raised.exception))

# verify there's only one item in the db
res = self.client.get(PRODUCTS_URL)
print(res.data)

添加这两行后,我收到以下错误:

<块引用>

“当前事务发生错误。您不能” django.db.transaction.TransactionManagementError:发生错误 当前交易。直到结束时您才能执行查询 “原子”块。

我该如何解决这个问题?

0 个答案:

没有答案