Search code examples
pythondjangopython-unittestdjango-testingdjango-tests

How to test a named CheckConstraint or ValidationError is raised in unittests?


I am unittesting validations and checkconstraints on my model:

class MyModel(models.Model):
    title = models.CharField()

    class Meta:
        models.CheckConstraint(
            check=~Q(title='Word'),
            name='title_cannot_be_word'
        ),

    def clean(self):
       error_dict = {}
            if self.title == 'Word':
                error_dict['title'] = 'Title can not be Word'

       if error_dict:
            raise ValidationError(error_dict)

In my tests.py:

def test_validation(self):

    with self.assertRaises(ValidationError):
        m = MyModel(title='Word')
        m.clean()

def test_constraint(self):

    with self.assertRaises(Integrity):
        m = MyModel.objects.create(title='Word')

This all works fine, however in practice I have multiple CheckConstraints and ValidationErrors for different fields, so I want to be able to test that the correct error has been raised.

How can I test a named CheckConstraint like title_cannot_be_word is raised, or a named ValidationError like error_dict['title'] is raised?


Solution

  • You can obtain a reference to the exception, and then continue validating:

    def test_validation(self):
        with self.assertRaises(ValidationError) as ex:
            m = MyModel(title='Word')
            m.clean()
        exception = ex.exception
        self.assertTrue(hasattr(exception, 'error_dict'))
        self.assertIn('title', exception.error_dict)

    As for an IntegrityError, this does not contain any fields, it is just Exception with parameters. You might want to check if the name of the exception is in the string representation:

    def test_constraint(self):
        with self.assertRaises(Integrity) as ex:
            MyModel.objects.create(title='Word')
        exception = ex.exception
        self.assertIn('title_cannot_be_word', str(exception))