Как написать модульный тест ValidationError в ответе с помощью client.post()

У меня есть модель с валидатором времени raise ValidationError('End time cannot be earlier than start time')

Я хочу написать модульный тест, используя client.post() с недействительными данными (from_time > to_time), и я ожидал, что ValidationError появится в этом тесте.

Вы можете взглянуть на пример документа о том, как написать тестовый пример https://docs.djangoproject.com/en/dev/topics/testing/tools/#example. В вашем случае это будет выглядеть так (обратите внимание, что это всего лишь пример, поэтому измените его в соответствии с вашим случаем):

Это для проверки из сериализатора/api DRF:

import unittest
from django.test import Client
import datetime

class SimpleTest(unittest.TestCase):
    def setUp(self):
        # Every test needs a client.
        self.client = Client()

    def test_invalid_date(self):
        # Issue a POST request.
        response = self.client.post(
                   '/your/path/url',
                   {
                      'start_time': datetime.datetime(2020, 5, 17), 
                      'end_time': datetime.datetime(2020, 5, 15) #notice end_time smaller than start_time
                   },
              )

        self.assertEqual(response.status_code, 400)

        # Check that the rendered context json have error message.
        self.assertEqual(response.json()['key']['path']['to']['error']['message'], 'End time cannot be earlier than start time')

Для валидации из валидатора модели(doc):

Например, в вашей модели валидатор модели выглядит следующим образом:

def custom_validator(value):
    if value.end_time < value.start_time:
      raise ValidationError('End time cannot be earlier than start time')

Ваш модульный тест будет выглядеть следующим образом, используйте python assertRaisesRegex() для проверки типа python ValidationError:

import unittest
from django.test import Client
import datetime

class SimpleTest(unittest.TestCase):

    def test_invalid_date(self):
        with self.assertRaisesRegex(ValidationError, 'End time cannot be earlier than start time'):
             your_model = YourModel(
               start_time=datetime.datetime(2020, 5, 17), 
               end_time=datetime.datetime(2020, 5, 15) 
             )
             your_model.full_clean()

При использовании pytest-django ваш тест будет выглядеть следующим образом:

from datetime import datetime, timedelta

def test_error_when_to_time_before_from_time(db, admin_client):
    invalid_data = {
        "from_time": datetime.today(),
        "to_time": datetime.today() - timedelta(days=2),
    }
    response = admin_client.post("<url-to-endpoint>", data=invalid_data)
    assert response.status_code == 400
    assert "End time cannot be earlier than start time" in response.content.decode()

Pytest-django предоставляет вам авторизованного клиента администратора и создает временную базу данных в зависимости от ваших текущих миграций для каждого теста. После теста изменения снова удаляются.

Я также добавил "TEST_REQUEST_DEFAULT_FORMAT": "json", в словарь REST_FRAMEWORK в settings.py.

Вернуться на верх