0

I have a model Student, which, among other fields, contains two fields; mob_student for storing the student's mobile number and mob_parent for storing their parent's number.

I have designed the Student model such that a Student object is only successfully entered into the database if at least one mobile number is provided.

Since such a validation requires access to more than a single field, I created the following clean() method.

class Student(AbstractUser):

    def clean(self):

        if not (self.mob_parent or self.mob_student):
            raise ValidationError("Please enter at least one mobile number.")

In Django's Admin site, this works perfectly:

  • when the admin provides at least one number, the object is stored successfully;
  • when the admin does not provide either number, the message error appears at the top of the form.

Even though my model is working exactly as I want it to, the test case I wrote seems to be flawed.

Here are two test units:

test_create_user_with_one_mobile() tests a valid entry.

test_create_user_without_mobile_disallowed() tests an invalid entry.

class StudentModelTest(TestCase):

def setUp(self):
        Locality.objects.create(name='Valletta')
        School.objects.create(
            name='Foobar Academy',
            locality=Locality.objects.get(id=1),
            type='public',
        )

def test_create_user_with_one_mobile(self):

    myStudent = Student.objects.create(
        email='foobar@gmail.com',
        first_name='Thomas',
        last_name='Johnson',
        school=School.objects.get(id=1),
        mob_parent='99112233',
        locality=Locality.objects.get(id=1),
    )

    self.assertTrue(isinstance(myStudent, Student))

def test_create_user_without_mobile_disallowed(self):

    myStudent = Student.objects.create(
        email='foobar@gmail.com',
        first_name='Thomas',
        last_name='Johnson',
        school=School.objects.get(id=1),
        locality=Locality.objects.get(id=1),
    )

    self.assertFalse(isinstance(myStudent, Student)) # FAILS

In the latter, the Student object seems to have been instantiated successfully despite not having a single mobile number specified. How so?

ryanvb92
  • 311
  • 2
  • 13
  • 1
    `clean()` is not actually called on `save()` as indicated in the docs. `Note, however, that like Model.full_clean(), a model’s clean() method is not invoked when you call your model’s save() method.` https://docs.djangoproject.com/en/2.0/ref/models/instances/#django.db.models.Model.clean – Nicholas Claude LeBlanc Jul 17 '18 at 21:04
  • you have to call the clean method in a try - except ValidationError and if the ValidationError is raised your test should pass. `myStudent.clean()` would return `None` if it passed. you are really trying to validate the response of the response of the clean method – Nicholas Claude LeBlanc Jul 17 '18 at 21:12
  • you can also initialize a form instance and test if form.is_valid() is False when your data is passed through. I believe the clean method is called in that instance and an object would not be created because the form validation would fail – Nicholas Claude LeBlanc Jul 17 '18 at 21:21

0 Answers0