CheckConstraint in Django model not triggering in unittest.TestCase (AssertionError: IntegrityError not raised)
I have a Model class with a series of constraints that I am attempting to test, and I am unable to get these constraints to return an IntegrityError in testing. The class is as follows:
from django.db import models
from django.db.models import CheckConstraint, Q, UniqueConstraint
class Products(models.Model):
sku = models.CharField(primary_key=True, max_length=8)
barcode = models.CharField(unique=True, max_length=14, blank=True, null=True)
name = models.TextField(blank=True, null=True)
rrp = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
status = models.TextField()
manufacturer = models.TextField(blank=True, null=True)
brand = models.TextField(blank=True, null=True)
country_of_origin = models.TextField(blank=True, null=True)
last_updated = models.DateField(blank=True, null=True)
date_published = models.DateField(blank=True, null=True)
exclusive = models.BooleanField(blank=True, null=True)
class Meta:
managed = False
db_table = 'product'
constraints = [
CheckConstraint(
condition=Q(status__in=['Draft', 'Live', 'Discontinued']),
name='check_status',
violation_error_message="status field must be on of the following: 'Draft', 'Live', 'Discontinued'",
),
CheckConstraint(
condition=~(Q(date_published__isnull=False) & Q(status__in=['Draft', 'Discontinued'])),
name='check_date_published',
violation_error_message="Product with status 'Draft' or 'Discontinued' cannot have a date_published value"
),
UniqueConstraint(fields=['barcode'], name='unique_barcode'),
UniqueConstraint(fields=['sku', 'exclusive'], name='unique_sku_and_exclusive'),
UniqueConstraint(fields=['sku', 'status'], name='unique_sku_and_status')
]
The 'managed' value is flipped in 0001_initial.py when tests are run. The IntegrityError I'm using is from django.db.utils
and not sqlite3
, however the save() method isn't returning any exceptions to begin with, so the issue is not coming from the wrong version of IntegrityError.
from django.db.utils import IntegrityError
from django.test import TestCase
from .models import Products
class ProductTestCase(TestCase):
def setUp(self):
self.product = Products.objects.create(
sku = '12345678',
barcode = '5666777888999',
name = 'Test Product 1',
rrp = 999,
status = 'Live',
manufacturer = '',
brand = 'Test Brand',
country_of_origin = 'China',
last_updated = '2025-01-01',
date_published = '2025-01-01',
exclusive = False
)
def test_invalid_product_status_not_null(self):
"""Test product can't be made with an invalid status value"""
self.product.status = 'WrongStatus'
with self.assertRaises(IntegrityError):
self.product.save()
I have attempted simply creating a Products object in the with clause with only sku and status, I've attempted having the constraints both inside and outside of the constraints list in the meta, but I just can't get the CheckConstraint to trigger. Am I misunderstanding when constraints are supposed to trigger? Or am I writing the Q objects incorrectly?