1

I have the following model in models.py:

@python_2_unicode_compatible
class Session(ModelCommon): # ModelCommon is an abstract Model which extends from models.Model with the fields name(CharField) and enabled(BooleanField).
    """
    Model Session with foreign key to Model Event.
    """
    event = models.ForeignKey(verbose_name=_('Event'), to=Event, default=None, null=False, blank=False)
    start_datetime = models.DateTimeField(verbose_name=_('Session Starts'), default=None, null=False, blank=False)
    end_datetime = models.DateTimeField(verbose_name=_('Session Ends'), default=None, null=False, blank=False)
    available = models.BooleanField(verbose_name=_('Available'), default=True, null=False, blank=False)
    price = models.DecimalField(verbose_name=_('Price'), max_digits=10, decimal_places=2,
                                validators=[MinValueValidator(0.00)],
                                default=None, null=False, blank=False)

When I test my Model that it shouldn't be saved in Database if price is negative, it doesn't raise an Exception as it should.

test_models.py:

class SessionTestCase(TestCase):
    """
    Case of tests for Model Session.
    """

    def setUpTestData(cls):
        """
        This method is used to declare dummy data that could be used by all tests.
        """
        cls.test_event = Event(name='Test Event Name for Session', enabled=True)
        cls.test_event.save()

    def setUp(self):
        """
        This method is used to run code before each test.
        """
        self.session = Session(event=self.test_event, name='Session No1', enabled=True,
                               start_datetime=timezone.now() + timedelta(days=1),
                               end_datetime=timezone.now() + timedelta(days=3), price=0)


    def test_session_price_cannot_be_negative(self):
        """
        :return: Passed if Session object with negative price raises Exception.
        """
        self.session.price = -20.0
        self.assertRaises(Exception, lambda: self.session.save())

Finally, as I run my test_models.py, I get the following message:

Failure
Traceback (most recent call last):
    self.assertRaises(Exception, lambda: self.session.save())
AssertionError: Exception not raised
joaofguerreiro
  • 107
  • 3
  • 8

1 Answers1

1

Calling save() does not trigger validation. See the Django docs on validating objects for more info. You could call full_clean instead.

self.session.price = -20.0
self.assertRaises(Exception, lambda: self.session.full_clean())

Note that you can remove the lambda from your code and pass the callable. It would also be better to catch the more specific ValidationError rather than Exception.

self.session.price = -20.0
self.assertRaises(ValidationError, self.session.full_clean)
Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • 1
    This worked, thank you. I've overwritten the `save()` method in my Model so it includes `full_clean()`. I hope that can do the trick. – joaofguerreiro Apr 04 '17 at 13:59
  • If you call `full_clean()` in the save method, then validation will sometimes run twice. See [this question](http://stackoverflow.com/questions/12945339/is-this-the-way-to-validate-django-model-fields/12945692#12945692) for more info. – Alasdair Apr 04 '17 at 14:06